summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/script
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 10:22:43 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:36:28 +0000
commit271a6c3487a14599023a9106329505597638d793 (patch)
treee040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/third_party/blink/renderer/core/script
parent7b2ffa587235a47d4094787d72f38102089f402a (diff)
downloadqtwebengine-chromium-271a6c3487a14599023a9106329505597638d793.tar.gz
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21 Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/script')
-rw-r--r--chromium/third_party/blink/renderer/core/script/BUILD.gn23
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_pending_script.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_pending_script.h4
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_script.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_script.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/document_write_intervention.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h4
-rwxr-xr-xchromium/third_party/blink/renderer/core/script/generate_lapi_grdp.py65
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc140
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h22
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner_host.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/import_map.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/script/js_module_script.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/script/js_module_script.h3
-rw-r--r--chromium/third_party/blink/renderer/core/script/layered_api_module.h5
-rw-r--r--chromium/third_party/blink/renderer/core/script/layered_api_resources.h51
-rw-r--r--chromium/third_party/blink/renderer/core/script/layered_api_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/script/mock_script_element_base.h4
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator.h12
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.h6
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_pending_script.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_pending_script.h4
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver.h6
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.h3
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script_test.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.h10
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/PRESUBMIT.py39
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/README.md24
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/internal/reflection.mjs63
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/README.md3
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs75
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs128
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs224
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/track.mjs74
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/.eslintrc.js338
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/index.mjs280
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/.eslintrc.js337
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/docs/README.md297
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/docs/roaming-slot.pngbin0 -> 36729 bytes
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/find-element.mjs104
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/index.mjs57
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/sets.mjs24
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs407
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/async_iterator.mjs8
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs33
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp17
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/README.chromium12
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/index.mjs213
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/item-source.mjs47
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.mjs320
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.mjs64
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.mjs349
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.mjs531
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.mjs444
-rw-r--r--chromium/third_party/blink/renderer/core/script/script.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.h34
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_scheduling_type.h9
-rw-r--r--chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc153
-rw-r--r--chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h78
77 files changed, 3327 insertions, 2345 deletions
diff --git a/chromium/third_party/blink/renderer/core/script/BUILD.gn b/chromium/third_party/blink/renderer/core/script/BUILD.gn
index 1346b025962..ac7886ede65 100644
--- a/chromium/third_party/blink/renderer/core/script/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/script/BUILD.gn
@@ -58,6 +58,8 @@ blink_core_sources("script") {
"script_runner.cc",
"script_runner.h",
"script_scheduling_type.h",
+ "value_wrapper_synthetic_module_script.cc",
+ "value_wrapper_synthetic_module_script.h",
"worker_modulator_impl.cc",
"worker_modulator_impl.h",
"worklet_modulator_impl.cc",
@@ -73,3 +75,24 @@ blink_core_sources("script") {
jumbo_excluded_sources = [ "modulator.cc" ] # https://crbug.com/716395
}
+
+copy("layered_apis_elements_virtual_scroller_js") {
+ testonly = true
+
+ sources = [
+ "resources/layered_api/elements/virtual-scroller/find-element.mjs",
+ "resources/layered_api/elements/virtual-scroller/sets.mjs",
+ "resources/layered_api/elements/virtual-scroller/visibility-manager.mjs",
+ ]
+
+ outputs = [
+ "{{source_gen_dir}}/{{source_file_part}}",
+ ]
+}
+
+group("js_files_for_web_tests") {
+ testonly = true
+ data_deps = [
+ ":layered_apis_elements_virtual_scroller_js",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/core/script/classic_pending_script.cc b/chromium/third_party/blink/renderer/core/script/classic_pending_script.cc
index 3bd0f996731..67703f93bfd 100644
--- a/chromium/third_party/blink/renderer/core/script/classic_pending_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -18,10 +18,11 @@
#include "third_party/blink/renderer/core/script/document_write_intervention.h"
#include "third_party/blink/renderer/core/script/script_loader.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
+#include "third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
@@ -249,10 +250,13 @@ void ClassicPendingScript::NotifyFinished(Resource* resource) {
// It is possible to get back a script resource with integrity metadata
// for a request with an empty integrity attribute. In that case, the
- // integrity check should be skipped, so this check ensures that the
- // integrity attribute isn't empty in addition to checking if the
- // resource has empty integrity metadata.
- if (!element->IntegrityAttributeValue().IsEmpty()) {
+ // integrity check should be skipped, as the integrity may not have been
+ // "meant" for this specific request. If the resource is being served from
+ // the preload cache however, we know any associated integrity metadata and
+ // checks were destined for this request, so we cannot skip the integrity
+ // check.
+ if (!element->IntegrityAttributeValue().IsEmpty() ||
+ GetResource()->IsLinkPreload()) {
integrity_failure_ = GetResource()->IntegrityDisposition() !=
ResourceIntegrityDisposition::kPassed;
}
@@ -276,7 +280,7 @@ void ClassicPendingScript::NotifyFinished(Resource* resource) {
AdvanceReadyState(error_occurred ? kErrorOccurred : kReady);
}
-void ClassicPendingScript::Trace(blink::Visitor* visitor) {
+void ClassicPendingScript::Trace(Visitor* visitor) {
ResourceClient::Trace(visitor);
MemoryPressureListener::Trace(visitor);
PendingScript::Trace(visitor);
@@ -342,7 +346,7 @@ ClassicScript* ClassicPendingScript::GetSource(const KURL& document_url) const {
auto* fetcher = GetElement()->GetDocument().ContextDocument()->Fetcher();
// If the MIME check fails, which is considered as load failure.
if (!AllowedByNosniff::MimeTypeAsScript(
- fetcher->Context(), &fetcher->GetConsoleLogger(),
+ fetcher->GetUseCounter(), &fetcher->GetConsoleLogger(),
resource->GetResponse(), AllowedByNosniff::MimeTypeCheck::kLax)) {
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/script/classic_pending_script.h b/chromium/third_party/blink/renderer/core/script/classic_pending_script.h
index c9e135de659..ca495ebdd16 100644
--- a/chromium/third_party/blink/renderer/core/script/classic_pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/classic_pending_script.h
@@ -10,8 +10,8 @@
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
#include "third_party/blink/renderer/core/script/classic_script.h"
#include "third_party/blink/renderer/core/script/pending_script.h"
+#include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
-#include "third_party/blink/renderer/platform/memory_pressure_listener.h"
namespace blink {
@@ -58,7 +58,7 @@ class CORE_EXPORT ClassicPendingScript final : public PendingScript,
void SetStreamer(ScriptStreamer*);
void StreamingFinished();
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
mojom::ScriptType GetScriptType() const override {
return mojom::ScriptType::kClassic;
diff --git a/chromium/third_party/blink/renderer/core/script/classic_script.cc b/chromium/third_party/blink/renderer/core/script/classic_script.cc
index afe840f1bb7..df884115ba2 100644
--- a/chromium/third_party/blink/renderer/core/script/classic_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/classic_script.cc
@@ -13,7 +13,7 @@
namespace blink {
-void ClassicScript::Trace(blink::Visitor* visitor) {
+void ClassicScript::Trace(Visitor* visitor) {
Script::Trace(visitor);
visitor->Trace(script_source_code_);
}
diff --git a/chromium/third_party/blink/renderer/core/script/classic_script.h b/chromium/third_party/blink/renderer/core/script/classic_script.h
index b5da0ea28d7..e64a2118b1e 100644
--- a/chromium/third_party/blink/renderer/core/script/classic_script.h
+++ b/chromium/third_party/blink/renderer/core/script/classic_script.h
@@ -24,7 +24,7 @@ class CORE_EXPORT ClassicScript final : public Script {
script_source_code_(script_source_code),
sanitize_script_errors_(sanitize_script_errors) {}
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
const ScriptSourceCode& GetScriptSourceCode() const {
return script_source_code_;
diff --git a/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc b/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
index fbe4bfc38f9..e4bb75221db 100644
--- a/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
+++ b/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/script/document_write_intervention.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -34,7 +34,7 @@ void EmitWarningMayBeBlocked(const String& url, Document& document) {
document.AddConsoleMessage(
ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript,
mojom::ConsoleMessageLevel::kWarning, message));
- DVLOG(1) << message.Utf8().data();
+ DVLOG(1) << message.Utf8();
}
void EmitWarningNotBlocked(const String& url, Document& document) {
diff --git a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
index b8249e5a431..63ffbe076b0 100644
--- a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
@@ -27,7 +27,7 @@ class DynamicImportTreeClient final : public ModuleTreeClient {
ScriptPromiseResolver* promise_resolver)
: url_(url), modulator_(modulator), promise_resolver_(promise_resolver) {}
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
private:
// Implements ModuleTreeClient:
@@ -54,31 +54,30 @@ void DynamicImportTreeClient::NotifyModuleTreeLoadFinished(
ScriptState::Scope scope(script_state);
v8::Isolate* isolate = script_state->GetIsolate();
- // <spec step="2.5">If result is null, then:</spec>
+ // <spec step="6">If result is null, then:</spec>
if (!module_script) {
- // <spec step="2.5.1">Let completion be Completion { [[Type]]: throw,
+ // <spec step="6.1">Let completion be Completion { [[Type]]: throw,
// [[Value]]: a new TypeError, [[Target]]: empty }.</spec>
v8::Local<v8::Value> error = V8ThrowException::CreateTypeError(
isolate,
"Failed to fetch dynamically imported module: " + url_.GetString());
- // <spec step="2.5.2">Perform FinishDynamicImport(referencingScriptOrModule,
+ // <spec step="6.2">Perform FinishDynamicImport(referencingScriptOrModule,
// specifier, promiseCapability, completion).</spec>
promise_resolver_->Reject(error);
- // <spec step="2.5.3">Return.</spec>
+ // <spec step="6.3">Return.</spec>
return;
}
- // <spec step="2.6">Run the module script result, with the rethrow errors
+ // <spec step="7">Run the module script result, with the rethrow errors
// boolean set to true.</spec>
ScriptValue error = modulator_->ExecuteModule(
module_script, Modulator::CaptureEvalErrorFlag::kCapture);
- // <spec step="2.7">If running the module script throws an exception,
- // ...</spec>
+ // <spec step="8">If running the module script throws an exception, ...</spec>
if (!error.IsEmpty()) {
- // <spec step="2.7">... then perform
+ // <spec step="8">... then perform
// FinishDynamicImport(referencingScriptOrModule, specifier,
// promiseCapability, the thrown exception completion).</spec>
//
@@ -93,7 +92,7 @@ void DynamicImportTreeClient::NotifyModuleTreeLoadFinished(
return;
}
- // <spec step="2.8">Otherwise, perform
+ // <spec step="9">Otherwise, perform
// FinishDynamicImport(referencingScriptOrModule, specifier,
// promiseCapability, NormalCompletion(undefined)).</spec>
//
@@ -142,7 +141,7 @@ void DynamicImportTreeClient::NotifyModuleTreeLoadFinished(
promise_resolver_->Resolve(module_namespace);
}
-void DynamicImportTreeClient::Trace(blink::Visitor* visitor) {
+void DynamicImportTreeClient::Trace(Visitor* visitor) {
visitor->Trace(modulator_);
visitor->Trace(promise_resolver_);
ModuleTreeClient::Trace(visitor);
@@ -150,7 +149,7 @@ void DynamicImportTreeClient::Trace(blink::Visitor* visitor) {
} // namespace
-void DynamicModuleResolver::Trace(blink::Visitor* visitor) {
+void DynamicModuleResolver::Trace(Visitor* visitor) {
visitor->Trace(modulator_);
}
@@ -173,13 +172,10 @@ void DynamicModuleResolver::ResolveDynamically(
// (in ResolveModuleSpecifier()) and we need to clear the flag before that.
modulator_->ClearIsAcquiringImportMaps();
- // <spec step="1">Let referencing script be
+ // <spec step="4.1">Let referencing script be
// referencingScriptOrModule.[[HostDefined]].</spec>
- // <spec step="2">Run the following steps in parallel:</spec>
-
- // <spec step="2.1">Let url be the result of resolving a module specifier
- // given referencing script's base URL and specifier.</spec>
+ // <spec step="4.3">Set base URL to referencing script's base URL.</spec>
KURL base_url = referrer_info.BaseURL();
if (base_url.IsNull()) {
// ReferrerScriptInfo::BaseURL returns null if it should defer to referrer
@@ -187,25 +183,39 @@ void DynamicModuleResolver::ResolveDynamically(
base_url = referrer_resource_url;
}
if (base_url.IsNull()) {
- // In some cases, "referencing script" may not exist. Use the document's
- // base URL as last resort.
- // TODO(kouhei): Revisit this after
- // https://github.com/whatwg/html/issues/3295 resolved.
+ // The case where "referencing script" doesn't exist.
+ //
+ // <spec step="1">Let settings object be the current settings object.</spec>
+ //
+ // <spec step="2">Let base URL be settings object's API base URL.</spec>
base_url = ExecutionContext::From(modulator_->GetScriptState())->BaseURL();
}
DCHECK(!base_url.IsNull());
+ // <spec step="5">Fetch an import() module script graph given specifier, base
+ // URL, settings object, and fetch options. Wait until the algorithm
+ // asynchronously completes with result.</spec>
+ //
+ // <specdef label="fetch-an-import()-module-script-graph"
+ // href="https://html.spec.whatwg.org/C/#fetch-an-import()-module-script-graph">
+
+ // <spec label="fetch-an-import()-module-script-graph" step="1">Let url be the
+ // result of resolving a module specifier given base URL and specifier.</spec>
KURL url = modulator_->ResolveModuleSpecifier(specifier, base_url);
+
+ // <spec label="fetch-an-import()-module-script-graph" step="2">If url is
+ // failure, then asynchronously complete this algorithm with null, and abort
+ // these steps.</spec>
if (!url.IsValid()) {
- // <spec step="2.2">If url is failure, then:</spec>
+ // <spec step="6">If result is null, then:</spec>
//
- // <spec step="2.2.1">Let completion be Completion { [[Type]]: throw,
+ // <spec step="6.1">Let completion be Completion { [[Type]]: throw,
// [[Value]]: a new TypeError, [[Target]]: empty }.</spec>
v8::Isolate* isolate = modulator_->GetScriptState()->GetIsolate();
v8::Local<v8::Value> error = V8ThrowException::CreateTypeError(
isolate, "Failed to resolve module specifier '" + specifier + "'");
- // <spec step="2.2.2">Perform FinishDynamicImport(referencingScriptOrModule,
+ // <spec step="6.2">Perform FinishDynamicImport(referencingScriptOrModule,
// specifier, promiseCapability, completion).</spec>
//
// <spec
@@ -215,18 +225,19 @@ void DynamicModuleResolver::ResolveDynamically(
// »).</spec>
promise_resolver->Reject(error);
- // <spec step="2.2.3">Return.</spec>
+ // <spec step="6.3">Return.</spec>
return;
}
- // <spec step="2.3">Let options be the descendant script fetch options for
- // referencing script's fetch options.</spec>
+ // <spec step="4.4">Set fetch options to the descendant script fetch options
+ // for referencing script's fetch options.</spec>
//
// <spec
// href="https://html.spec.whatwg.org/C/#descendant-script-fetch-options"> For
// any given script fetch options options, the descendant script fetch options
// are a new script fetch options whose items all have the same values, except
// for the integrity metadata, which is instead the empty string.</spec>
+ //
// TODO(domfarolino): It has not yet been decided how a script's "importance"
// should affect its dynamic imports. There is discussion at
// https://github.com/whatwg/html/issues/3670, but for now there is no effect,
@@ -239,9 +250,12 @@ void DynamicModuleResolver::ResolveDynamically(
referrer_info.GetReferrerPolicy(),
mojom::FetchImportanceMode::kImportanceAuto);
- // <spec step="2.4">Fetch a module script graph given url, referencing
- // script's settings object, "script", and options. Wait until the algorithm
- // asynchronously completes with result.</spec>
+ // <spec label="fetch-an-import()-module-script-graph" step="3">Fetch a single
+ // module script given url, settings object, "script", options, settings
+ // object, "client", and with the top-level module fetch flag set. If the
+ // caller of this algorithm specified custom perform the fetch steps, pass
+ // those along as well. Wait until the algorithm asynchronously completes with
+ // result.</spec>
auto* tree_client = MakeGarbageCollected<DynamicImportTreeClient>(
url, modulator_.Get(), promise_resolver);
// TODO(kouhei): ExecutionContext::From(modulator_->GetScriptState()) is
@@ -254,10 +268,10 @@ void DynamicModuleResolver::ResolveDynamically(
mojom::RequestContextType::SCRIPT, options,
ModuleScriptCustomFetchType::kNone, tree_client);
- // Steps 2.[5-8] are implemented at
+ // Steps 6-9 are implemented at
// DynamicImportTreeClient::NotifyModuleLoadFinished.
- // <spec step="3">Return undefined.</spec>
+ // <spec step="10">Return undefined.</spec>
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h
index b97df2d5d5b..e73c78d383b 100644
--- a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h
+++ b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.h
@@ -23,7 +23,7 @@ class ScriptPromiseResolver;
class CORE_EXPORT DynamicModuleResolver final
: public GarbageCollected<DynamicModuleResolver> {
public:
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
explicit DynamicModuleResolver(Modulator* modulator)
: modulator_(modulator) {}
diff --git a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
index 90b5bbb5ef7..c85586c2393 100644
--- a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
@@ -47,7 +47,7 @@ class DynamicModuleResolverTestModulator final : public DummyModulator {
}
bool fetch_tree_was_called() const { return fetch_tree_was_called_; }
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
private:
// Implements Modulator:
@@ -101,7 +101,7 @@ class DynamicModuleResolverTestModulator final : public DummyModulator {
bool fetch_tree_was_called_ = false;
};
-void DynamicModuleResolverTestModulator::Trace(blink::Visitor* visitor) {
+void DynamicModuleResolverTestModulator::Trace(Visitor* visitor) {
visitor->Trace(script_state_);
visitor->Trace(pending_client_);
DummyModulator::Trace(visitor);
@@ -110,7 +110,7 @@ void DynamicModuleResolverTestModulator::Trace(blink::Visitor* visitor) {
// CaptureExportedStringFunction implements a javascript function
// with a single argument of type module namespace.
// CaptureExportedStringFunction captures the exported string value
-// from the module namespace as a blink::String, exposed via CapturedValue().
+// from the module namespace as a WTF::String, exposed via CapturedValue().
class CaptureExportedStringFunction final : public ScriptFunction {
public:
CaptureExportedStringFunction(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
index 1be2d76fbaf..a01b4a1df40 100644
--- a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
+++ b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
@@ -5,14 +5,14 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_IMPL_H_
-#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
#include "third_party/blink/renderer/platform/loader/fetch/https_state.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/script/generate_lapi_grdp.py b/chromium/third_party/blink/renderer/core/script/generate_lapi_grdp.py
index a05172b2019..fcb15ba5047 100755
--- a/chromium/third_party/blink/renderer/core/script/generate_lapi_grdp.py
+++ b/chromium/third_party/blink/renderer/core/script/generate_lapi_grdp.py
@@ -5,6 +5,7 @@
import sys
import os
+import re
def main():
@@ -40,42 +41,42 @@ def main():
-->'''
resource_list_in_header_file = ''
- modules = set()
-
+ # A list of (name, path)
+ modules = []
for root, _, filenames in sorted(os.walk(input_path)):
- relroot = os.path.relpath(root, input_path)
- if relroot == '.':
- # We don't include top-level files under resources/layered_api,
- # including generated resources.grdp.
- continue
-
- # Get e.g. "kKvStorage" for kv-storage.
- module_name = relroot.split('/')[0]
- module_name = "k" + module_name.title().replace('-', '')
- modules.add(module_name)
-
- for filename in sorted(filenames):
- if filename.startswith('.') or filename.startswith(
- 'README') or filename.startswith('OWNERS'):
- continue
- relpath = os.path.relpath(os.path.join(root, filename), input_path)
- relpath = relpath.replace('\\', '/')
- resource_id = relpath
- resource_id = resource_id.replace('/', '_')
- resource_id = resource_id.replace('-', '_')
- resource_id = resource_id.replace('.', '_')
- resource_id = resource_id.upper()
- resource_id = "IDR_LAYERED_API_" + resource_id
- resource_list_in_header_file += \
- ' {"%s",\n %s,\n Module::%s},\n' % (relpath, resource_id, module_name)
- print >> output_grdp_file, (
- ' <include name="%s" file="%s/%s" type="BINDATA" skip_minify="true" compress="gzip"/>'
- % (resource_id, input_relative_path, relpath))
- resource_list_in_header_file += '\n'
+ # A directory represents a built-in module if
+ # - it contains index.mjs (web-exposed module) or
+ # - the directory name is 'internal' (private module)
+ if 'index.mjs' in filenames or re.search(r'\binternal$', root):
+ # Get e.g. "kKvStorage" for kv-storage.
+ module_name = os.path.relpath(root, input_path)
+ module_name = "k" + re.sub(r'\W', '', module_name.title())
+ modules.append((module_name, root))
+
+ for module_name, module_path in modules:
+ for root, _, filenames in sorted(os.walk(module_path)):
+ for filename in sorted(filenames):
+ if filename.startswith('.') or filename.startswith(
+ 'README') or filename.startswith('OWNERS'):
+ continue
+ relpath = os.path.relpath(os.path.join(root, filename), input_path)
+ relpath = relpath.replace('\\', '/')
+ resource_id = relpath
+ resource_id = resource_id.replace('/', '_')
+ resource_id = resource_id.replace('-', '_')
+ resource_id = resource_id.replace('.', '_')
+ resource_id = resource_id.upper()
+ resource_id = "IDR_LAYERED_API_" + resource_id
+ resource_list_in_header_file += \
+ ' {"%s",\n %s,\n Module::%s},\n' % (relpath, resource_id, module_name)
+ print >> output_grdp_file, (
+ ' <include name="%s" file="%s/%s" type="BINDATA" skip_minify="true" compress="gzip"/>'
+ % (resource_id, input_relative_path, relpath))
+ resource_list_in_header_file += '\n'
print >> output_grdp_file, '</grit-part>'
module_list_in_header_file = ''
- for module in modules:
+ for module, _ in modules:
module_list_in_header_file += (' %s,\n' % module)
print >> output_module_header_file, '''// Copyright 2019 The Chromium Authors. All rights reserved.
diff --git a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc
index 2a22c04baf2..2bd8365bb0e 100644
--- a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc
+++ b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc
@@ -27,6 +27,7 @@
#include <inttypes.h>
#include <memory>
+#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/dom/document_parser_timing.h"
@@ -39,7 +40,7 @@
#include "third_party/blink/renderer/core/script/script_loader.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
-#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
@@ -160,6 +161,11 @@ void HTMLParserScriptRunner::Detach() {
parser_blocking_script_->Dispose();
parser_blocking_script_ = nullptr;
+ while (!force_deferred_scripts_.IsEmpty()) {
+ PendingScript* pending_script = force_deferred_scripts_.TakeFirst();
+ pending_script->Dispose();
+ }
+
while (!scripts_to_execute_after_parsing_.IsEmpty()) {
PendingScript* pending_script =
scripts_to_execute_after_parsing_.TakeFirst();
@@ -299,7 +305,14 @@ void HTMLParserScriptRunner::PendingScriptFinished(
return;
}
- host_->NotifyScriptLoaded(pending_script);
+ // Posting the script execution part to a new task so that we can allow
+ // yielding for cooperative scheduling. Cooperative scheduling requires that
+ // the Blink C++ stack be thin when it executes JavaScript.
+ document_->GetTaskRunner(TaskType::kInternalContinueScriptLoading)
+ ->PostTask(FROM_HERE,
+ WTF::Bind(&HTMLParserScriptRunnerHost::NotifyScriptLoaded,
+ WrapPersistent(host_.Get()),
+ WrapPersistent(pending_script)));
}
// <specdef href="https://html.spec.whatwg.org/C/#scriptEndTag">
@@ -412,38 +425,61 @@ void HTMLParserScriptRunner::ExecuteScriptsWaitingForResources() {
ExecuteParsingBlockingScripts();
}
+PendingScript* HTMLParserScriptRunner::TryTakeReadyScriptWaitingForParsing(
+ HeapDeque<Member<PendingScript>>* waiting_scripts) {
+ DCHECK(!waiting_scripts->IsEmpty());
+
+ // <spec step="3.1">Spin the event loop until the first script in the list
+ // of scripts that will execute when the document has finished parsing has
+ // its "ready to be parser-executed" flag set and the parser's Document has
+ // no style sheet that is blocking scripts.</spec>
+ //
+ // TODO(hiroshige): Add check for style sheet blocking defer scripts
+ // https://github.com/whatwg/html/issues/3890
+ if (!waiting_scripts->front()->IsReady()) {
+ waiting_scripts->front()->WatchForLoad(this);
+ TraceParserBlockingScript(waiting_scripts->front().Get(),
+ !document_->IsScriptExecutionReady());
+ waiting_scripts->front()->MarkParserBlockingLoadStartTime();
+ return nullptr;
+ }
+ return waiting_scripts->TakeFirst();
+}
+
// <specdef href="https://html.spec.whatwg.org/C/#stop-parsing">
//
// <spec step="3">If the list of scripts that will execute when the document has
// finished parsing is not empty, run these substeps:</spec>
+//
+// This will also run any forced deferred scripts before running any developer
+// deferred scripts.
bool HTMLParserScriptRunner::ExecuteScriptsWaitingForParsing() {
TRACE_EVENT0("blink",
"HTMLParserScriptRunner::executeScriptsWaitingForParsing");
- while (!scripts_to_execute_after_parsing_.IsEmpty()) {
+ while (!force_deferred_scripts_.IsEmpty() ||
+ !scripts_to_execute_after_parsing_.IsEmpty()) {
DCHECK(!IsExecutingScript());
DCHECK(!HasParserBlockingScript());
- DCHECK(scripts_to_execute_after_parsing_.front()->IsExternalOrModule());
-
- // <spec step="3.1">Spin the event loop until the first script in the list
- // of scripts that will execute when the document has finished parsing has
- // its "ready to be parser-executed" flag set and the parser's Document has
- // no style sheet that is blocking scripts.</spec>
- //
- // TODO(hiroshige): Is the latter part checked anywhere?
- if (!scripts_to_execute_after_parsing_.front()->IsReady()) {
- scripts_to_execute_after_parsing_.front()->WatchForLoad(this);
- TraceParserBlockingScript(scripts_to_execute_after_parsing_.front().Get(),
- !document_->IsScriptExecutionReady());
- scripts_to_execute_after_parsing_.front()
- ->MarkParserBlockingLoadStartTime();
- return false;
- }
+ DCHECK(scripts_to_execute_after_parsing_.IsEmpty() ||
+ scripts_to_execute_after_parsing_.front()->IsExternalOrModule());
// <spec step="3.3">Remove the first script element from the list of scripts
// that will execute when the document has finished parsing (i.e. shift out
// the first entry in the list).</spec>
- PendingScript* first = scripts_to_execute_after_parsing_.TakeFirst();
+ PendingScript* first = nullptr;
+
+ // First execute the scripts that were forced-deferred. If no such scripts
+ // are present, then try executing scripts that were deferred by the web
+ // developer.
+ if (!force_deferred_scripts_.IsEmpty()) {
+ first = TryTakeReadyScriptWaitingForParsing(&force_deferred_scripts_);
+ } else {
+ first = TryTakeReadyScriptWaitingForParsing(
+ &scripts_to_execute_after_parsing_);
+ }
+ if (!first)
+ return false;
// <spec step="3.2">Execute the first script in the list of scripts that
// will execute when the document has finished parsing.</spec>
@@ -494,6 +530,7 @@ void HTMLParserScriptRunner::RequestDeferredScript(
pending_script->StartStreamingIfPossible();
}
+ DCHECK(!script_loader->IsForceDeferred());
DCHECK(pending_script->IsExternalOrModule());
// <spec href="https://html.spec.whatwg.org/C/#prepare-a-script"
@@ -503,6 +540,25 @@ void HTMLParserScriptRunner::RequestDeferredScript(
scripts_to_execute_after_parsing_.push_back(pending_script);
}
+void HTMLParserScriptRunner::RequestForceDeferredScript(
+ ScriptLoader* script_loader) {
+ PendingScript* pending_script =
+ script_loader->TakePendingScript(ScriptSchedulingType::kForceDefer);
+ if (!pending_script)
+ return;
+
+ if (!pending_script->IsReady()) {
+ pending_script->StartStreamingIfPossible();
+ }
+
+ DCHECK(script_loader->IsForceDeferred());
+
+ // Add the element to the end of the list of forced deferred scripts that will
+ // execute when the document has finished parsing associated with the Document
+ // of the parser that created the element.
+ force_deferred_scripts_.push_back(pending_script);
+}
+
// The initial steps for 'An end tag whose tag name is "script"'
// <specdef href="https://html.spec.whatwg.org/C/#scriptEndTag">
// <specdef label="prepare-a-script"
@@ -544,7 +600,11 @@ void HTMLParserScriptRunner::ProcessScriptElementInternal(
return;
if (script_loader->WillExecuteWhenDocumentFinishedParsing()) {
+ // Developer deferred.
RequestDeferredScript(script_loader);
+ } else if (script_loader->IsForceDeferred()) {
+ // Force defer this otherwise parser-blocking script.
+ RequestForceDeferredScript(script_loader);
} else if (script_loader->ReadyToBeParserExecuted()) {
// <spec label="prepare-a-script" step="26.E">... it's an HTML parser
// whose script nesting level is not greater than one, ...</spec>
@@ -589,10 +649,48 @@ void HTMLParserScriptRunner::ProcessScriptElementInternal(
}
}
-void HTMLParserScriptRunner::Trace(blink::Visitor* visitor) {
+void HTMLParserScriptRunner::RecordMetricsAtParseEnd() const {
+ // This method is called just before starting execution of force defer
+ // scripts in order to capture the all force deferred scripts in
+ // |force_deferred_scripts_| before any are popped for execution.
+
+ if (!document_->GetFrame())
+ return;
+
+ if (!force_deferred_scripts_.IsEmpty()) {
+ uint32_t force_deferred_external_script_count = 0;
+ for (const auto& pending_script : force_deferred_scripts_) {
+ if (pending_script->IsExternal())
+ force_deferred_external_script_count++;
+ }
+ if (document_->IsInMainFrame()) {
+ UMA_HISTOGRAM_COUNTS_100("Blink.Script.ForceDeferredScripts.Mainframe",
+ force_deferred_scripts_.size());
+ UMA_HISTOGRAM_COUNTS_100(
+ "Blink.Script.ForceDeferredScripts.Mainframe.External",
+ force_deferred_external_script_count);
+ if (document_->UkmRecorder()) {
+ ukm::builders::PreviewsDeferAllScript(document_->UkmSourceID())
+ .Setforce_deferred_scripts_mainframe(force_deferred_scripts_.size())
+ .Setforce_deferred_scripts_mainframe_external(
+ force_deferred_external_script_count)
+ .Record(document_->UkmRecorder());
+ }
+ } else {
+ UMA_HISTOGRAM_COUNTS_100("Blink.Script.ForceDeferredScripts.Subframe",
+ force_deferred_scripts_.size());
+ UMA_HISTOGRAM_COUNTS_100(
+ "Blink.Script.ForceDeferredScripts.Subframe.External",
+ force_deferred_external_script_count);
+ }
+ }
+}
+
+void HTMLParserScriptRunner::Trace(Visitor* visitor) {
visitor->Trace(document_);
visitor->Trace(host_);
visitor->Trace(parser_blocking_script_);
+ visitor->Trace(force_deferred_scripts_);
visitor->Trace(scripts_to_execute_after_parsing_);
PendingScriptClient::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h
index f9b1dce95a2..a3f88c0dff3 100644
--- a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h
+++ b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h
@@ -93,6 +93,8 @@ class HTMLParserScriptRunner final
void ExecuteScriptsWaitingForResources();
// Invoked when parsing is stopping, to execute any deferred scripts.
+ // This includes forced deferred scripts as well as developer deferred
+ // scripts.
bool ExecuteScriptsWaitingForParsing();
bool HasParserBlockingScript() const;
@@ -100,7 +102,11 @@ class HTMLParserScriptRunner final
return !!reentry_permit_->ScriptNestingLevel();
}
- void Trace(blink::Visitor*) override;
+ // Records metrics related to the parsing phase. To be called when parsing
+ // is preparing to stop but before |ExecuteScriptsWaitingForParsing|.
+ void RecordMetricsAtParseEnd() const;
+
+ void Trace(Visitor*) override;
const char* NameInHeapSnapshot() const override {
return "HTMLParserScriptRunner";
}
@@ -115,6 +121,7 @@ class HTMLParserScriptRunner final
void RequestParsingBlockingScript(ScriptLoader*);
void RequestDeferredScript(ScriptLoader*);
+ void RequestForceDeferredScript(ScriptLoader*);
// Processes the provided script element, but does not execute any
// parsing-blocking scripts that may remain after execution.
@@ -129,6 +136,12 @@ class HTMLParserScriptRunner final
void PossiblyFetchBlockedDocWriteScript(PendingScript*);
+ // Takes and returns the first PendingScript from |waiting_scripts| if it is
+ // ready for execution. Otherwise, informs it that |this| is a
+ // PendingScriptClient to be informed when it is ready.
+ PendingScript* TryTakeReadyScriptWaitingForParsing(
+ HeapDeque<Member<PendingScript>>* waiting_scripts);
+
scoped_refptr<HTMLParserReentryPermit> reentry_permit_;
Member<Document> document_;
Member<HTMLParserScriptRunnerHost> host_;
@@ -136,6 +149,13 @@ class HTMLParserScriptRunner final
// https://html.spec.whatwg.org/C/#pending-parsing-blocking-script
Member<PendingScript> parser_blocking_script_;
+ // Scripts that were force deferred by the defer all script optimization.
+ // These scripts will be executed after parsing but before
+ // |scripts_to_execute_after_parsing_|. This is an ordered list.
+ // https://crbug.com/976061
+ HeapDeque<Member<PendingScript>> force_deferred_scripts_;
+
+ // Scripts that were deferred by the web developer. This is an ordered list.
// https://html.spec.whatwg.org/C/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing
HeapDeque<Member<PendingScript>> scripts_to_execute_after_parsing_;
diff --git a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner_host.h b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner_host.h
index dd5f4fbe1c4..1a4770c0a2a 100644
--- a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner_host.h
+++ b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner_host.h
@@ -37,7 +37,7 @@ class PendingScript;
class CORE_EXPORT HTMLParserScriptRunnerHost : public GarbageCollectedMixin {
public:
virtual ~HTMLParserScriptRunnerHost() = default;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
virtual void NotifyScriptLoaded(PendingScript*) = 0;
virtual HTMLInputStream& InputStream() = 0;
diff --git a/chromium/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h b/chromium/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h
index cedad851068..02738ad8bc5 100644
--- a/chromium/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h
+++ b/chromium/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h
@@ -28,7 +28,7 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/script/import_map.cc b/chromium/third_party/blink/renderer/core/script/import_map.cc
index fceaddd75a9..c78d79dda49 100644
--- a/chromium/third_party/blink/renderer/core/script/import_map.cc
+++ b/chromium/third_party/blink/renderer/core/script/import_map.cc
@@ -187,7 +187,7 @@ ImportMap* ImportMap::Create(const Modulator& modulator_for_built_in_modules,
values.clear();
}
if (values.size() == 2) {
- if (blink::layered_api::GetBuiltinPath(values[0]).IsNull()) {
+ if (layered_api::GetBuiltinPath(values[0]).IsNull()) {
AddIgnoredValueMessage(
logger, entry.first,
"Fallback from a non-builtin URL is not yet supported.");
@@ -282,8 +282,8 @@ base::Optional<KURL> ImportMap::Resolve(const ParsedSpecifier& parsed_specifier,
for (const KURL& value : matched->value) {
const KURL complete_url = postfix.IsEmpty() ? value : KURL(value, postfix);
- if (blink::layered_api::ResolveFetchingURL(*modulator_for_built_in_modules_,
- complete_url)
+ if (layered_api::ResolveFetchingURL(*modulator_for_built_in_modules_,
+ complete_url)
.IsValid()) {
*debug_message = "Import Map: \"" + key + "\" matches with \"" +
matched->key + "\" and is mapped to " +
diff --git a/chromium/third_party/blink/renderer/core/script/js_module_script.cc b/chromium/third_party/blink/renderer/core/script/js_module_script.cc
index d53409bf7c6..8b12c6ac851 100644
--- a/chromium/third_party/blink/renderer/core/script/js_module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/js_module_script.cc
@@ -6,8 +6,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/script/module_record_resolver.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "v8/include/v8.h"
@@ -166,21 +164,6 @@ JSModuleScript::JSModuleScript(Modulator* settings_object,
start_position_(start_position),
produce_cache_data_(produce_cache_data) {}
-void JSModuleScript::RunScriptOnWorker(WorkerGlobalScope& worker_global_scope) {
- DCHECK(worker_global_scope.IsContextThread());
-
- WorkerReportingProxy& worker_reporting_proxy =
- worker_global_scope.ReportingProxy();
-
- worker_reporting_proxy.WillEvaluateModuleScript();
- // This |error| is always null because the second argument is |kReport|.
- // TODO(nhiroki): Catch an error when an evaluation error happens.
- // (https://crbug.com/680046)
- ScriptValue error = SettingsObject()->ExecuteModule(
- this, Modulator::CaptureEvalErrorFlag::kReport);
- worker_reporting_proxy.DidEvaluateModuleScript(error.IsEmpty());
-}
-
String JSModuleScript::InlineSourceTextForCSP() const {
return source_text_.ToString();
}
@@ -199,7 +182,7 @@ void JSModuleScript::ProduceCache() {
produce_cache_data_ = nullptr;
}
-void JSModuleScript::Trace(blink::Visitor* visitor) {
+void JSModuleScript::Trace(Visitor* visitor) {
visitor->Trace(produce_cache_data_);
ModuleScript::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/script/js_module_script.h b/chromium/third_party/blink/renderer/core/script/js_module_script.h
index db070c73340..61089f896de 100644
--- a/chromium/third_party/blink/renderer/core/script/js_module_script.h
+++ b/chromium/third_party/blink/renderer/core/script/js_module_script.h
@@ -57,7 +57,7 @@ class CORE_EXPORT JSModuleScript final : public ModuleScript,
void ProduceCache() override;
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
const char* NameInHeapSnapshot() const override { return "JSModuleScript"; }
private:
@@ -74,7 +74,6 @@ class CORE_EXPORT JSModuleScript final : public ModuleScript,
ModuleRecordProduceCacheData* produce_cache_data);
const TextPosition& StartPosition() const { return start_position_; }
- void RunScriptOnWorker(WorkerGlobalScope&) override;
String InlineSourceTextForCSP() const override;
// For CSP check.
diff --git a/chromium/third_party/blink/renderer/core/script/layered_api_module.h b/chromium/third_party/blink/renderer/core/script/layered_api_module.h
index 28809a991c0..7dd7d687dab 100644
--- a/chromium/third_party/blink/renderer/core/script/layered_api_module.h
+++ b/chromium/third_party/blink/renderer/core/script/layered_api_module.h
@@ -15,7 +15,10 @@ namespace layered_api {
enum class Module {
kBlank,
- kVirtualScroller,
+ kElementsInternal,
+ kElementsSwitch,
+ kElementsToast,
+ kElementsVirtualScroller,
kKvStorage,
};
diff --git a/chromium/third_party/blink/renderer/core/script/layered_api_resources.h b/chromium/third_party/blink/renderer/core/script/layered_api_resources.h
index f822934e6ff..98be4b31e1a 100644
--- a/chromium/third_party/blink/renderer/core/script/layered_api_resources.h
+++ b/chromium/third_party/blink/renderer/core/script/layered_api_resources.h
@@ -29,6 +29,35 @@ struct LayeredAPIResource {
const LayeredAPIResource kLayeredAPIResources[] = {
{"blank/index.mjs", IDR_LAYERED_API_BLANK_INDEX_MJS, Module::kBlank},
+ {"elements/internal/reflection.mjs",
+ IDR_LAYERED_API_ELEMENTS_INTERNAL_REFLECTION_MJS,
+ Module::kElementsInternal},
+
+ {"elements/switch/face_utils.mjs",
+ IDR_LAYERED_API_ELEMENTS_SWITCH_FACE_UTILS_MJS, Module::kElementsSwitch},
+ {"elements/switch/index.mjs", IDR_LAYERED_API_ELEMENTS_SWITCH_INDEX_MJS,
+ Module::kElementsSwitch},
+ {"elements/switch/style.mjs", IDR_LAYERED_API_ELEMENTS_SWITCH_STYLE_MJS,
+ Module::kElementsSwitch},
+ {"elements/switch/track.mjs", IDR_LAYERED_API_ELEMENTS_SWITCH_TRACK_MJS,
+ Module::kElementsSwitch},
+
+ {"elements/toast/index.mjs", IDR_LAYERED_API_ELEMENTS_TOAST_INDEX_MJS,
+ Module::kElementsToast},
+
+ {"elements/virtual-scroller/find-element.mjs",
+ IDR_LAYERED_API_ELEMENTS_VIRTUAL_SCROLLER_FIND_ELEMENT_MJS,
+ Module::kElementsVirtualScroller},
+ {"elements/virtual-scroller/index.mjs",
+ IDR_LAYERED_API_ELEMENTS_VIRTUAL_SCROLLER_INDEX_MJS,
+ Module::kElementsVirtualScroller},
+ {"elements/virtual-scroller/sets.mjs",
+ IDR_LAYERED_API_ELEMENTS_VIRTUAL_SCROLLER_SETS_MJS,
+ Module::kElementsVirtualScroller},
+ {"elements/virtual-scroller/visibility-manager.mjs",
+ IDR_LAYERED_API_ELEMENTS_VIRTUAL_SCROLLER_VISIBILITY_MANAGER_MJS,
+ Module::kElementsVirtualScroller},
+
{"kv-storage/async_iterator.mjs",
IDR_LAYERED_API_KV_STORAGE_ASYNC_ITERATOR_MJS, Module::kKvStorage},
{"kv-storage/idb_utils.mjs", IDR_LAYERED_API_KV_STORAGE_IDB_UTILS_MJS,
@@ -36,28 +65,6 @@ const LayeredAPIResource kLayeredAPIResources[] = {
{"kv-storage/index.mjs", IDR_LAYERED_API_KV_STORAGE_INDEX_MJS,
Module::kKvStorage},
- {"virtual-scroller/index.mjs", IDR_LAYERED_API_VIRTUAL_SCROLLER_INDEX_MJS,
- Module::kVirtualScroller},
- {"virtual-scroller/item-source.mjs",
- IDR_LAYERED_API_VIRTUAL_SCROLLER_ITEM_SOURCE_MJS,
- Module::kVirtualScroller},
- {"virtual-scroller/virtual-repeater.mjs",
- IDR_LAYERED_API_VIRTUAL_SCROLLER_VIRTUAL_REPEATER_MJS,
- Module::kVirtualScroller},
- {"virtual-scroller/virtual-scroller.mjs",
- IDR_LAYERED_API_VIRTUAL_SCROLLER_VIRTUAL_SCROLLER_MJS,
- Module::kVirtualScroller},
-
- {"virtual-scroller/layouts/layout-1d-base.mjs",
- IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_BASE_MJS,
- Module::kVirtualScroller},
- {"virtual-scroller/layouts/layout-1d-grid.mjs",
- IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_GRID_MJS,
- Module::kVirtualScroller},
- {"virtual-scroller/layouts/layout-1d.mjs",
- IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_MJS,
- Module::kVirtualScroller},
-
};
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/script/layered_api_test.cc b/chromium/third_party/blink/renderer/core/script/layered_api_test.cc
index 28ac45737df..f318f7fc807 100644
--- a/chromium/third_party/blink/renderer/core/script/layered_api_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/layered_api_test.cc
@@ -16,9 +16,7 @@ namespace {
class LayeredAPITestModulator final : public DummyModulator {
public:
bool BuiltInModuleInfraEnabled() const override { return true; }
- bool BuiltInModuleEnabled(blink::layered_api::Module) const override {
- return true;
- }
+ bool BuiltInModuleEnabled(layered_api::Module) const override { return true; }
};
class LayeredAPITest : public testing::Test {
diff --git a/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h b/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
index 2afb66aefb4..2722f3a7971 100644
--- a/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
+++ b/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
@@ -55,9 +55,7 @@ class MockScriptElementBase
void(HTMLScriptElementOrSVGScriptElement&));
MOCK_CONST_METHOD0(Loader, ScriptLoader*());
- void Trace(blink::Visitor* visitor) override {
- ScriptElementBase::Trace(visitor);
- }
+ void Trace(Visitor* visitor) override { ScriptElementBase::Trace(visitor); }
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/modulator.h b/chromium/third_party/blink/renderer/core/script/modulator.h
index 350858d9972..9f67b4e5afa 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator.h
+++ b/chromium/third_party/blink/renderer/core/script/modulator.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULATOR_H_
#include "base/single_thread_task_runner.h"
-#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
@@ -44,7 +44,7 @@ class CORE_EXPORT SingleModuleClient
public NameClient {
public:
virtual ~SingleModuleClient() = default;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
const char* NameInHeapSnapshot() const override {
return "SingleModuleClient";
}
@@ -59,7 +59,7 @@ class CORE_EXPORT ModuleTreeClient
public NameClient {
public:
virtual ~ModuleTreeClient() = default;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
const char* NameInHeapSnapshot() const override { return "ModuleTreeClient"; }
virtual void NotifyModuleTreeLoadFinished(ModuleScript*) = 0;
@@ -107,7 +107,7 @@ class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
static void SetModulator(ScriptState*, Modulator*);
static void ClearModulator(ScriptState*);
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
const char* NameInHeapSnapshot() const override { return "Modulator"; }
virtual ModuleRecordResolver* GetModuleRecordResolver() = 0;
@@ -122,8 +122,8 @@ class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
virtual bool IsScriptingDisabled() const = 0;
virtual bool BuiltInModuleInfraEnabled() const = 0;
- virtual bool BuiltInModuleEnabled(blink::layered_api::Module) const = 0;
- virtual void BuiltInModuleUseCount(blink::layered_api::Module) const = 0;
+ virtual bool BuiltInModuleEnabled(layered_api::Module) const = 0;
+ virtual void BuiltInModuleUseCount(layered_api::Module) const = 0;
// https://html.spec.whatwg.org/C/#fetch-a-module-script-tree
// https://html.spec.whatwg.org/C/#fetch-a-module-worker-script-tree
diff --git a/chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc b/chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc
index 441862b5a36..a3bcbe4b6ae 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc
+++ b/chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc
@@ -7,7 +7,6 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h"
@@ -18,6 +17,7 @@
#include "third_party/blink/renderer/core/script/module_record_resolver_impl.h"
#include "third_party/blink/renderer/core/script/parsed_specifier.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -52,33 +52,49 @@ bool ModulatorImplBase::BuiltInModuleInfraEnabled() const {
GetExecutionContext());
}
-bool ModulatorImplBase::BuiltInModuleEnabled(
- blink::layered_api::Module module) const {
+bool ModulatorImplBase::BuiltInModuleEnabled(layered_api::Module module) const {
DCHECK(BuiltInModuleInfraEnabled());
+ if (RuntimeEnabledFeatures::BuiltInModuleAllEnabled())
+ return true;
switch (module) {
- case blink::layered_api::Module::kBlank:
+ case layered_api::Module::kBlank:
return true;
- case blink::layered_api::Module::kVirtualScroller:
+ case layered_api::Module::kKvStorage:
+ return RuntimeEnabledFeatures::BuiltInModuleKvStorageEnabled(
+ GetExecutionContext());
+ case layered_api::Module::kElementsInternal:
+ // Union of conditions of KElementsSwitch and kElementsToast.
+ return RuntimeEnabledFeatures::BuiltInModuleSwitchElementEnabled();
+ case layered_api::Module::kElementsSwitch:
+ return RuntimeEnabledFeatures::BuiltInModuleSwitchElementEnabled();
+ case layered_api::Module::kElementsToast:
return RuntimeEnabledFeatures::BuiltInModuleAllEnabled();
- case blink::layered_api::Module::kKvStorage:
- return RuntimeEnabledFeatures::BuiltInModuleAllEnabled() ||
- RuntimeEnabledFeatures::BuiltInModuleKvStorageEnabled(
- GetExecutionContext());
+ case layered_api::Module::kElementsVirtualScroller:
+ return false;
}
}
void ModulatorImplBase::BuiltInModuleUseCount(
- blink::layered_api::Module module) const {
+ layered_api::Module module) const {
DCHECK(BuiltInModuleInfraEnabled());
DCHECK(BuiltInModuleEnabled(module));
switch (module) {
- case blink::layered_api::Module::kBlank:
+ case layered_api::Module::kBlank:
break;
- case blink::layered_api::Module::kVirtualScroller:
+ case layered_api::Module::kElementsInternal:
+ break;
+ case layered_api::Module::kElementsSwitch:
+ UseCounter::Count(GetExecutionContext(),
+ WebFeature::kBuiltInModuleSwitchImported);
+ break;
+ case layered_api::Module::kElementsToast:
+ UseCounter::Count(GetExecutionContext(), WebFeature::kBuiltInModuleToast);
+ break;
+ case layered_api::Module::kElementsVirtualScroller:
UseCounter::Count(GetExecutionContext(),
WebFeature::kBuiltInModuleVirtualScroller);
break;
- case blink::layered_api::Module::kKvStorage:
+ case layered_api::Module::kKvStorage:
UseCounter::Count(GetExecutionContext(),
WebFeature::kBuiltInModuleKvStorage);
break;
@@ -96,32 +112,9 @@ void ModulatorImplBase::FetchTree(
const ScriptFetchOptions& options,
ModuleScriptCustomFetchType custom_fetch_type,
ModuleTreeClient* client) {
- // <spec label="fetch-a-module-script-tree" step="2">Perform the internal
- // module script graph fetching procedure given url, settings object,
- // destination, options, settings object, visited set, "client", and with the
- // top-level module fetch flag set. If the caller of this algorithm specified
- // custom perform the fetch steps, pass those along as well.</spec>
-
- // <spec label="fetch-a-module-worker-script-tree" step="3">Perform the
- // internal module script graph fetching procedure given url, fetch client
- // settings object, destination, options, module map settings object, visited
- // set, "client", and with the top-level module fetch flag set. If the caller
- // of this algorithm specified custom perform the fetch steps, pass those
- // along as well.</spec>
-
ModuleTreeLinker::Fetch(url, fetch_client_settings_object_fetcher,
destination, options, this, custom_fetch_type,
tree_linker_registry_, client);
-
- // <spec label="fetch-a-module-script-tree" step="3">When the internal module
- // script graph fetching procedure asynchronously completes with result,
- // asynchronously complete this algorithm with result.</spec>
-
- // <spec label="fetch-a-module-worker-script-tree" step="4">When the internal
- // module script graph fetching procedure asynchronously completes with
- // result, asynchronously complete this algorithm with result.</spec>
-
- // Note: We delegate to ModuleTreeLinker to notify ModuleTreeClient.
}
void ModulatorImplBase::FetchDescendantsForInlineScript(
@@ -265,14 +258,14 @@ ModuleImportMeta ModulatorImplBase::HostGetImportMetaProperties(
ModuleRecord record) const {
// <spec step="1">Let module script be moduleRecord.[[HostDefined]].</spec>
const ModuleScript* module_script =
- module_record_resolver_->GetHostDefined(record);
+ module_record_resolver_->GetModuleScriptFromModuleRecord(record);
DCHECK(module_script);
- // <spec step="2">Let urlString be module script's base URL,
+ // <spec step="3">Let urlString be module script's base URL,
// serialized.</spec>
String url_string = module_script->BaseURL().GetString();
- // <spec step="3">Return « Record { [[Key]]: "url", [[Value]]: urlString }
+ // <spec step="4">Return « Record { [[Key]]: "url", [[Value]]: urlString }
// ».</spec>
return ModuleImportMeta(url_string);
}
@@ -416,7 +409,7 @@ ScriptValue ModulatorImplBase::ExecuteModule(
return ScriptValue();
}
-void ModulatorImplBase::Trace(blink::Visitor* visitor) {
+void ModulatorImplBase::Trace(Visitor* visitor) {
visitor->Trace(script_state_);
visitor->Trace(map_);
visitor->Trace(tree_linker_registry_);
diff --git a/chromium/third_party/blink/renderer/core/script/modulator_impl_base.h b/chromium/third_party/blink/renderer/core/script/modulator_impl_base.h
index 53780b19229..6721f1cb8af 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator_impl_base.h
+++ b/chromium/third_party/blink/renderer/core/script/modulator_impl_base.h
@@ -27,7 +27,7 @@ class ScriptState;
class ModulatorImplBase : public Modulator {
public:
~ModulatorImplBase() override;
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
protected:
explicit ModulatorImplBase(ScriptState*);
@@ -42,8 +42,8 @@ class ModulatorImplBase : public Modulator {
bool IsScriptingDisabled() const override;
bool BuiltInModuleInfraEnabled() const override;
- bool BuiltInModuleEnabled(blink::layered_api::Module) const override;
- void BuiltInModuleUseCount(blink::layered_api::Module) const override;
+ bool BuiltInModuleEnabled(layered_api::Module) const override;
+ void BuiltInModuleUseCount(layered_api::Module) const override;
ModuleRecordResolver* GetModuleRecordResolver() override {
return module_record_resolver_.Get();
diff --git a/chromium/third_party/blink/renderer/core/script/module_map.cc b/chromium/third_party/blink/renderer/core/script/module_map.cc
index f8fc91cf97f..d38ecfd0038 100644
--- a/chromium/third_party/blink/renderer/core/script/module_map.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_map.cc
@@ -25,7 +25,7 @@ class ModuleMap::Entry final : public GarbageCollectedFinalized<Entry>,
explicit Entry(ModuleMap*);
~Entry() override {}
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
const char* NameInHeapSnapshot() const override { return "ModuleMap::Entry"; }
// Notify fetched |m_moduleScript| to the client asynchronously.
@@ -53,7 +53,7 @@ ModuleMap::Entry::Entry(ModuleMap* map) : map_(map) {
DCHECK(map_);
}
-void ModuleMap::Entry::Trace(blink::Visitor* visitor) {
+void ModuleMap::Entry::Trace(Visitor* visitor) {
visitor->Trace(module_script_);
visitor->Trace(map_);
visitor->Trace(clients_);
@@ -100,7 +100,7 @@ ModuleMap::ModuleMap(Modulator* modulator)
DCHECK(modulator);
}
-void ModuleMap::Trace(blink::Visitor* visitor) {
+void ModuleMap::Trace(Visitor* visitor) {
visitor->Trace(map_);
visitor->Trace(modulator_);
visitor->Trace(loader_registry_);
@@ -137,7 +137,7 @@ void ModuleMap::FetchSingleModuleScript(
// <spec step="3">If moduleMap[url] exists, asynchronously complete this
// algorithm with moduleMap[url], and abort these steps.</spec>
//
- // <spec step="12">Set moduleMap[url] to module script, and asynchronously
+ // <spec step="14">Set moduleMap[url] to module script, and asynchronously
// complete this algorithm with module script.</spec>
if (client)
entry->AddClient(client);
diff --git a/chromium/third_party/blink/renderer/core/script/module_map.h b/chromium/third_party/blink/renderer/core/script/module_map.h
index fa0018a3cf9..46d98e67aa3 100644
--- a/chromium/third_party/blink/renderer/core/script/module_map.h
+++ b/chromium/third_party/blink/renderer/core/script/module_map.h
@@ -33,7 +33,7 @@ class CORE_EXPORT ModuleMap final : public GarbageCollected<ModuleMap>,
public:
explicit ModuleMap(Modulator*);
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
const char* NameInHeapSnapshot() const override { return "ModuleMap"; }
// https://html.spec.whatwg.org/C/#fetch-a-single-module-script
diff --git a/chromium/third_party/blink/renderer/core/script/module_map_test.cc b/chromium/third_party/blink/renderer/core/script/module_map_test.cc
index da2f4ab72f2..6df17a931d6 100644
--- a/chromium/third_party/blink/renderer/core/script/module_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_map_test.cc
@@ -30,7 +30,7 @@ class TestSingleModuleClient final : public SingleModuleClient {
TestSingleModuleClient() = default;
~TestSingleModuleClient() override {}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(module_script_);
SingleModuleClient::Trace(visitor);
}
@@ -64,7 +64,8 @@ class TestModuleRecordResolver final : public ModuleRecordResolver {
FAIL() << "UnregisterModuleScript shouldn't be called in ModuleMapTest";
}
- const ModuleScript* GetHostDefined(const ModuleRecord&) const override {
+ const ModuleScript* GetModuleScriptFromModuleRecord(
+ const ModuleRecord&) const override {
NOTREACHED();
return nullptr;
}
@@ -87,7 +88,7 @@ class ModuleMapTestModulator final : public DummyModulator {
explicit ModuleMapTestModulator(ScriptState*);
~ModuleMapTestModulator() override {}
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
TestModuleRecordResolver* GetTestModuleRecordResolver() {
return resolver_.Get();
@@ -117,12 +118,12 @@ class ModuleMapTestModulator final : public DummyModulator {
TestRequest* test_request = MakeGarbageCollected<TestRequest>(
ModuleScriptCreationParams(
request.Url(), ParkableString(String("").ReleaseImpl()), nullptr,
- request.GetResourceRequest().GetFetchCredentialsMode()),
+ request.GetResourceRequest().GetCredentialsMode()),
client);
modulator_->test_requests_.push_back(test_request);
}
String DebugName() const override { return "TestModuleScriptFetcher"; }
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
ModuleScriptFetcher::Trace(visitor);
visitor->Trace(modulator_);
}
@@ -152,7 +153,7 @@ class ModuleMapTestModulator final : public DummyModulator {
client_->NotifyFetchFinished(*params_,
HeapVector<Member<ConsoleMessage>>());
}
- void Trace(blink::Visitor* visitor) { visitor->Trace(client_); }
+ void Trace(Visitor* visitor) { visitor->Trace(client_); }
private:
base::Optional<ModuleScriptCreationParams> params_;
@@ -168,7 +169,7 @@ ModuleMapTestModulator::ModuleMapTestModulator(ScriptState* script_state)
: script_state_(script_state),
resolver_(MakeGarbageCollected<TestModuleRecordResolver>()) {}
-void ModuleMapTestModulator::Trace(blink::Visitor* visitor) {
+void ModuleMapTestModulator::Trace(Visitor* visitor) {
visitor->Trace(test_requests_);
visitor->Trace(script_state_);
visitor->Trace(resolver_);
@@ -198,8 +199,7 @@ class ModuleMapTest : public PageTestBase {
void ModuleMapTest::SetUp() {
PageTestBase::SetUp(IntSize(500, 500));
- GetDocument().SetURL(KURL("https://example.com"));
- GetDocument().SetSecurityOrigin(SecurityOrigin::Create(GetDocument().Url()));
+ NavigateTo(KURL("https://example.com"));
modulator_ = MakeGarbageCollected<ModuleMapTestModulator>(
ToScriptStateForMainWorld(&GetFrame()));
map_ = MakeGarbageCollected<ModuleMap>(modulator_);
diff --git a/chromium/third_party/blink/renderer/core/script/module_pending_script.cc b/chromium/third_party/blink/renderer/core/script/module_pending_script.cc
index cfe0735ec4f..29449ea2056 100644
--- a/chromium/third_party/blink/renderer/core/script/module_pending_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_pending_script.cc
@@ -31,7 +31,7 @@ void ModulePendingScriptTreeClient::NotifyModuleTreeLoadFinished(
pending_script_->NotifyModuleTreeLoadFinished();
}
-void ModulePendingScriptTreeClient::Trace(blink::Visitor* visitor) {
+void ModulePendingScriptTreeClient::Trace(Visitor* visitor) {
visitor->Trace(module_script_);
visitor->Trace(pending_script_);
ModuleTreeClient::Trace(visitor);
@@ -54,7 +54,7 @@ void ModulePendingScript::DisposeInternal() {
module_tree_client_ = nullptr;
}
-void ModulePendingScript::Trace(blink::Visitor* visitor) {
+void ModulePendingScript::Trace(Visitor* visitor) {
visitor->Trace(module_tree_client_);
PendingScript::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/script/module_pending_script.h b/chromium/third_party/blink/renderer/core/script/module_pending_script.h
index b0253af0d6c..230d4632c4d 100644
--- a/chromium/third_party/blink/renderer/core/script/module_pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/module_pending_script.h
@@ -29,7 +29,7 @@ class ModulePendingScriptTreeClient final : public ModuleTreeClient {
ModuleScript* GetModuleScript() const { return module_script_; }
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
private:
// Implements ModuleTreeClient
@@ -55,7 +55,7 @@ class CORE_EXPORT ModulePendingScript : public PendingScript {
return module_tree_client_->GetModuleScript();
}
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
private:
// PendingScript
diff --git a/chromium/third_party/blink/renderer/core/script/module_record_resolver.h b/chromium/third_party/blink/renderer/core/script/module_record_resolver.h
index fb075478d8f..5fb8d6c3b7f 100644
--- a/chromium/third_party/blink/renderer/core/script/module_record_resolver.h
+++ b/chromium/third_party/blink/renderer/core/script/module_record_resolver.h
@@ -26,7 +26,7 @@ class CORE_EXPORT ModuleRecordResolver
: public GarbageCollectedFinalized<ModuleRecordResolver> {
public:
virtual ~ModuleRecordResolver() = default;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
// Notifies the ModuleRecordResolver that a ModuleScript exists.
// This hook gives a chance for the resolver impl to populate module record
@@ -36,8 +36,8 @@ class CORE_EXPORT ModuleRecordResolver
// Notifies the ModuleRecordResolver to clear its ModuleScript mapping.
virtual void UnregisterModuleScript(const ModuleScript*) = 0;
- // Corresponds to the spec concept "[[HostDefined]]".
- virtual const ModuleScript* GetHostDefined(const ModuleRecord&) const = 0;
+ virtual const ModuleScript* GetModuleScriptFromModuleRecord(
+ const ModuleRecord&) const = 0;
// Implements "Runtime Semantics: HostResolveImportedModule"
// https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule
diff --git a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.cc b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.cc
index 212ee50da5e..46b15431539 100644
--- a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.cc
@@ -40,7 +40,7 @@ void ModuleRecordResolverImpl::UnregisterModuleScript(
record_to_module_script_map_.erase(module_script->Record());
}
-const ModuleScript* ModuleRecordResolverImpl::GetHostDefined(
+const ModuleScript* ModuleRecordResolverImpl::GetModuleScriptFromModuleRecord(
const ModuleRecord& record) const {
const auto it = record_to_module_script_map_.find(record);
CHECK_NE(it, record_to_module_script_map_.end())
@@ -58,38 +58,47 @@ ModuleRecord ModuleRecordResolverImpl::Resolve(
ExceptionState& exception_state) {
DVLOG(1) << "ModuleRecordResolverImpl::resolve(specifier=\"" << specifier
<< ", referrer.hash=" << ModuleRecordHash::GetHash(referrer) << ")";
+ // <spec step="3">If referencingScriptOrModule is not null, then:</spec>
+ //
+ // Currently this function implements the spec before
+ // https://github.com/tc39/proposal-dynamic-import is applied, i.e. where
+ // |referencingScriptOrModule| was always a non-null module script.
- // <spec step="1">Let referencing script be
- // referencingScriptOrModule.[[HostDefined]].</spec>
- const ModuleScript* referrer_module = GetHostDefined(referrer);
-
- // <spec step="2">Let moduleMap be referencing script's settings object's
- // module map.</spec>
+ // <spec step="3.2">Set settings object to referencing script's settings
+ // object.</spec>
//
- // Note: Blink finds out "module script's settings object"
- // (Modulator) from context where HostResolveImportedModule was called.
+ // <spec step="4">Let moduleMap be settings object's module map.</spec>
+ //
+ // These are |modulator_| and |this|, respectively, because module script's
+ // settings object is always the current settings object in Blink.
+
+ // <spec step="3.1">Let referencing script be
+ // referencingScriptOrModule.[[HostDefined]].</spec>
+ const ModuleScript* referrer_module =
+ GetModuleScriptFromModuleRecord(referrer);
- // <spec step="3">Let url be the result of resolving a module specifier given
- // referencing script's base URL and specifier.</spec>
+ // <spec step="3.3">Set base URL to referencing script's base URL.</spec>
+ // <spec step="5">Let url be the result of resolving a module specifier given
+ // base URL and specifier.</spec>
KURL url = referrer_module->ResolveModuleSpecifier(specifier);
- // <spec step="4">Assert: url is never failure, because resolving a module
+ // <spec step="6">Assert: url is never failure, because resolving a module
// specifier must have been previously successful with these same two
- // arguments.</spec>
+ // arguments ...</spec>
DCHECK(url.IsValid());
- // <spec step="5">Let resolved module script be moduleMap[url]. (This entry
+ // <spec step="7">Let resolved module script be moduleMap[url]. (This entry
// must exist for us to have gotten to this point.)</spec>
ModuleScript* module_script = modulator_->GetFetchedModuleScript(url);
- // <spec step="6">Assert: resolved module script is a module script (i.e., is
+ // <spec step="8">Assert: resolved module script is a module script (i.e., is
// not null or "fetching").</spec>
//
- // <spec step="7">Assert: resolved module script's record is not null.</spec>
+ // <spec step="9">Assert: resolved module script's record is not null.</spec>
DCHECK(module_script);
CHECK(!module_script->Record().IsNull());
- // <spec step="8">Return resolved module script's record.</spec>
+ // <spec step="10">Return resolved module script's record.</spec>
return module_script->Record();
}
@@ -99,7 +108,7 @@ void ModuleRecordResolverImpl::ContextDestroyed(ExecutionContext*) {
record_to_module_script_map_.clear();
}
-void ModuleRecordResolverImpl::Trace(blink::Visitor* visitor) {
+void ModuleRecordResolverImpl::Trace(Visitor* visitor) {
ModuleRecordResolver::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
visitor->Trace(record_to_module_script_map_);
diff --git a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h
index ecd381f27e3..ee9ec555b52 100644
--- a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h
+++ b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h
@@ -30,7 +30,7 @@ class CORE_EXPORT ModuleRecordResolverImpl final
ExecutionContext* execution_context)
: ContextLifecycleObserver(execution_context), modulator_(modulator) {}
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
USING_GARBAGE_COLLECTED_MIXIN(ModuleRecordResolverImpl);
private:
@@ -38,7 +38,8 @@ class CORE_EXPORT ModuleRecordResolverImpl final
void RegisterModuleScript(const ModuleScript*) final;
void UnregisterModuleScript(const ModuleScript*) final;
- const ModuleScript* GetHostDefined(const ModuleRecord&) const final;
+ const ModuleScript* GetModuleScriptFromModuleRecord(
+ const ModuleRecord&) const final;
// Implements "Runtime Semantics: HostResolveImportedModule" per HTML spec.
// https://html.spec.whatwg.org/C/#hostresolveimportedmodule(referencingscriptormodule,-specifier))
diff --git a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
index d369141fc7b..0b59125c96c 100644
--- a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
@@ -25,7 +25,7 @@ class ModuleRecordResolverImplTestModulator final : public DummyModulator {
ModuleRecordResolverImplTestModulator() {}
~ModuleRecordResolverImplTestModulator() override {}
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
void SetScriptState(ScriptState* script_state) {
script_state_ = script_state;
@@ -57,7 +57,7 @@ class ModuleRecordResolverImplTestModulator final : public DummyModulator {
Member<ModuleScript> module_script_;
};
-void ModuleRecordResolverImplTestModulator::Trace(blink::Visitor* visitor) {
+void ModuleRecordResolverImplTestModulator::Trace(Visitor* visitor) {
visitor->Trace(script_state_);
visitor->Trace(module_script_);
DummyModulator::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/core/script/module_script.cc b/chromium/third_party/blink/renderer/core/script/module_script.cc
index 4879fe71667..16fbb40347e 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_script.cc
@@ -6,6 +6,8 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/script/module_record_resolver.h"
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "v8/include/v8.h"
@@ -90,7 +92,7 @@ KURL ModuleScript::ResolveModuleSpecifier(const String& module_request,
return url;
}
-void ModuleScript::Trace(blink::Visitor* visitor) {
+void ModuleScript::Trace(Visitor* visitor) {
visitor->Trace(settings_object_);
visitor->Trace(record_.UnsafeCast<v8::Value>());
visitor->Trace(parse_error_);
@@ -104,6 +106,21 @@ void ModuleScript::RunScript(LocalFrame* frame, const SecurityOrigin*) {
Modulator::CaptureEvalErrorFlag::kReport);
}
+void ModuleScript::RunScriptOnWorker(WorkerGlobalScope& worker_global_scope) {
+ DCHECK(worker_global_scope.IsContextThread());
+
+ WorkerReportingProxy& worker_reporting_proxy =
+ worker_global_scope.ReportingProxy();
+
+ worker_reporting_proxy.WillEvaluateModuleScript();
+ // This |error| is always null because the second argument is |kReport|.
+ // TODO(nhiroki): Catch an error when an evaluation error happens.
+ // (https://crbug.com/680046)
+ ScriptValue error = SettingsObject()->ExecuteModule(
+ this, Modulator::CaptureEvalErrorFlag::kReport);
+ worker_reporting_proxy.DidEvaluateModuleScript(error.IsEmpty());
+}
+
std::ostream& operator<<(std::ostream& stream,
const ModuleScript& module_script) {
stream << "ModuleScript[" << &module_script;
diff --git a/chromium/third_party/blink/renderer/core/script/module_script.h b/chromium/third_party/blink/renderer/core/script/module_script.h
index 45e7fe86874..50d32f0ed33 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.h
+++ b/chromium/third_party/blink/renderer/core/script/module_script.h
@@ -48,7 +48,7 @@ class CORE_EXPORT ModuleScript : public Script {
KURL ResolveModuleSpecifier(const String& module_request,
String* failure_reason = nullptr) const;
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
virtual void ProduceCache() {}
@@ -67,6 +67,7 @@ class CORE_EXPORT ModuleScript : public Script {
return mojom::ScriptType::kModule;
}
void RunScript(LocalFrame*, const SecurityOrigin*) override;
+ void RunScriptOnWorker(WorkerGlobalScope&) override;
friend class ModuleTreeLinkerTestModulator;
diff --git a/chromium/third_party/blink/renderer/core/script/module_script_test.cc b/chromium/third_party/blink/renderer/core/script/module_script_test.cc
index 204391421b7..6d1849c14f5 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_script_test.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/script/js_module_script.h"
+#include "third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h"
#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
@@ -35,7 +36,7 @@ class ModuleScriptTestModulator final : public DummyModulator {
return Vector<ModuleRequest>();
}
- void Trace(blink::Visitor* visitor) override {
+ void Trace(Visitor* visitor) override {
visitor->Trace(script_state_);
DummyModulator::Trace(visitor);
}
@@ -82,6 +83,14 @@ class ModuleScriptTest : public ::testing::Test {
ScriptFetchOptions());
}
+ static ValueWrapperSyntheticModuleScript*
+ CreateValueWrapperSyntheticModuleScript(Modulator* modulator,
+ v8::Local<v8::Value> local_value) {
+ return ValueWrapperSyntheticModuleScript::CreateWithDefaultExport(
+ local_value, modulator, KURL("https://fox.url/script.js"),
+ KURL("https://fox.url/"), ScriptFetchOptions());
+ }
+
// Tests |window.foo| is set correctly, and reset |window.foo| for the next
// test.
static void TestFoo(V8TestingScope& scope) {
@@ -239,4 +248,14 @@ TEST_F(ModuleScriptTest, V8CodeCache) {
V8CodeCache::TagForCodeCache(cache_handler)));
}
-} // namespace blink
+TEST_F(ModuleScriptTest, ValueWrapperSyntheticModuleScript) {
+ V8TestingScope scope;
+ v8::Local<v8::Value> local_value(v8::Number::New(scope.GetIsolate(), 1234));
+ Modulator* modulator =
+ MakeGarbageCollected<ModuleScriptTestModulator>(scope.GetScriptState());
+ ValueWrapperSyntheticModuleScript* module_script =
+ CreateValueWrapperSyntheticModuleScript(modulator, local_value);
+ ASSERT_FALSE(module_script->Record().IsNull());
+}
+
+} // namespace blink \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/pending_script.cc b/chromium/third_party/blink/renderer/core/script/pending_script.cc
index b43e498c25a..b8fe2d8ab33 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.cc
@@ -25,15 +25,15 @@
#include "third_party/blink/renderer/core/script/pending_script.h"
-#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_parser_timing.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
namespace blink {
@@ -72,7 +72,7 @@ void PendingScript::Dispose() {
DCHECK(!IsWatchingForLoad());
starting_position_ = TextPosition::BelowRangePosition();
- parser_blocking_load_start_time_ = TimeTicks();
+ parser_blocking_load_start_time_ = base::TimeTicks();
DisposeInternal();
element_ = nullptr;
@@ -122,7 +122,7 @@ ScriptElementBase* PendingScript::GetElement() const {
void PendingScript::MarkParserBlockingLoadStartTime() {
DCHECK(parser_blocking_load_start_time_.is_null());
- parser_blocking_load_start_time_ = CurrentTimeTicks();
+ parser_blocking_load_start_time_ = base::TimeTicks::Now();
}
// <specdef href="https://html.spec.whatwg.org/C/#execute-the-script-block">
@@ -172,7 +172,7 @@ void PendingScript::ExecuteScriptBlock(const KURL& document_url) {
const bool was_canceled = WasCanceled();
const bool is_external = IsExternal();
const bool created_during_document_write = WasCreatedDuringDocumentWrite();
- const TimeTicks parser_blocking_load_start_time =
+ const base::TimeTicks parser_blocking_load_start_time =
ParserBlockingLoadStartTime();
const bool is_controlled_by_script_runner = IsControlledByScriptRunner();
ScriptElementBase* element = element_;
@@ -192,7 +192,7 @@ void PendingScript::ExecuteScriptBlockInternal(
bool was_canceled,
bool is_external,
bool created_during_document_write,
- TimeTicks parser_blocking_load_start_time,
+ base::TimeTicks parser_blocking_load_start_time,
bool is_controlled_by_script_runner) {
Document& element_document = element->GetDocument();
Document* context_document = element_document.ContextDocument();
@@ -204,17 +204,17 @@ void PendingScript::ExecuteScriptBlockInternal(
return;
}
- if (parser_blocking_load_start_time > TimeTicks()) {
+ if (parser_blocking_load_start_time > base::TimeTicks()) {
DocumentParserTiming::From(element_document)
.RecordParserBlockedOnScriptLoadDuration(
- CurrentTimeTicks() - parser_blocking_load_start_time,
+ base::TimeTicks::Now() - parser_blocking_load_start_time,
created_during_document_write);
}
if (was_canceled)
return;
- TimeTicks script_exec_start_time = CurrentTimeTicks();
+ base::TimeTicks script_exec_start_time = base::TimeTicks::Now();
{
if (element->ElementHasDuplicateAttributes()) {
@@ -235,48 +235,51 @@ void PendingScript::ExecuteScriptBlockInternal(
IgnoreDestructiveWriteCountIncrementer incrementer(
needs_increment ? context_document : nullptr);
- // <spec step="4">Let old script element be the value to which the script
- // element's node document's currentScript object was most recently
+ // <spec step="4.A.1">Let old script element be the value to which the
+ // script element's node document's currentScript object was most recently
// set.</spec>
//
// This is implemented as push/popCurrentScript().
- // <spec step="5">Switch on the script's type:</spec>
- //
- // <spec step="5.A">"classic"</spec>
+ // <spec step="4">Switch on the script's type:</spec>
+
+ // <spec step="4.A">"classic"</spec>
//
- // <spec step="5.A.1">If the script element's root is not a shadow root,
+ // <spec step="4.A.2">If the script element's root is not a shadow root,
// then set the script element's node document's currentScript attribute to
// the script element. Otherwise, set it to null.</spec>
//
- // <spec step="5.B">"module"</spec>
+ // Note: The shadow root check is implemented in
+ // HTMLScriptElement::SetScriptElementForBinding().
+
+ // <spec step="4.B">"module"</spec>
//
- // <spec step="5.B.1">Set the script element's node document's currentScript
- // attribute to null.</spec>
+ // <spec step="4.B.1">Assert: The script element's node document's
+ // currentScript attribute is null.</spec>
ScriptElementBase* current_script = nullptr;
if (script->GetScriptType() == mojom::ScriptType::kClassic)
current_script = element;
context_document->PushCurrentScript(current_script);
- // <spec step="5.A">"classic"</spec>
+ // <spec step="4.A">"classic"</spec>
//
- // <spec step="5.A.2">Run the classic script given by the script's
+ // <spec step="4.A.3">Run the classic script given by the script's
// script.</spec>
//
// Note: This is where the script is compiled and actually executed.
//
- // <spec step="5.B">"module"</spec>
+ // <spec step="4.B">"module"</spec>
//
- // <spec step="5.B.2">Run the module script given by the script's
+ // <spec step="4.B.2">Run the module script given by the script's
// script.</spec>
script->RunScript(context_document->GetFrame(),
element_document.GetSecurityOrigin());
- // <spec step="6">Set the script element's node document's currentScript
+ // <spec step="4.A.4">Set the script element's node document's currentScript
// attribute to old script element.</spec>
context_document->PopCurrentScript(current_script);
- // <spec step="7">Decrement the ignore-destructive-writes counter of
+ // <spec step="5">Decrement the ignore-destructive-writes counter of
// neutralized doc, if it was incremented in the earlier step.</spec>
//
// Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer.
@@ -289,17 +292,17 @@ void PendingScript::ExecuteScriptBlockInternal(
if (!is_controlled_by_script_runner) {
DocumentParserTiming::From(element_document)
.RecordParserBlockedOnScriptExecutionDuration(
- CurrentTimeTicks() - script_exec_start_time,
+ base::TimeTicks::Now() - script_exec_start_time,
created_during_document_write);
}
- // <spec step="8">If the script is from an external file, then fire an event
+ // <spec step="6">If the script is from an external file, then fire an event
// named load at the script element.</spec>
if (is_external)
element->DispatchLoadEvent();
}
-void PendingScript::Trace(blink::Visitor* visitor) {
+void PendingScript::Trace(Visitor* visitor) {
visitor->Trace(element_);
visitor->Trace(client_);
visitor->Trace(original_context_document_);
@@ -315,6 +318,7 @@ bool PendingScript::IsControlledByScriptRunner() const {
case ScriptSchedulingType::kParserBlocking:
case ScriptSchedulingType::kParserBlockingInline:
case ScriptSchedulingType::kImmediate:
+ case ScriptSchedulingType::kForceDefer:
return false;
case ScriptSchedulingType::kInOrder:
diff --git a/chromium/third_party/blink/renderer/core/script/pending_script.h b/chromium/third_party/blink/renderer/core/script/pending_script.h
index cfc8a018ca8..08b44d08616 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.h
@@ -53,7 +53,7 @@ class CORE_EXPORT PendingScriptClient : public GarbageCollectedMixin {
// streaming finishes.
virtual void PendingScriptFinished(PendingScript*) = 0;
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(Visitor* visitor) override {}
};
// A container for an script after "prepare a script" until it is executed.
@@ -73,7 +73,7 @@ class CORE_EXPORT PendingScript
// Returns the time the load of this script started blocking the parser, or
// zero if this script hasn't yet blocked the parser, in
// monotonicallyIncreasingTime.
- TimeTicks ParserBlockingLoadStartTime() const {
+ base::TimeTicks ParserBlockingLoadStartTime() const {
return parser_blocking_load_start_time_;
}
@@ -85,7 +85,7 @@ class CORE_EXPORT PendingScript
virtual mojom::ScriptType GetScriptType() const = 0;
- virtual void Trace(blink::Visitor*);
+ virtual void Trace(Visitor*);
const char* NameInHeapSnapshot() const override { return "PendingScript"; }
// Returns nullptr when "script's script is null", i.e. an error occurred.
@@ -153,7 +153,7 @@ class CORE_EXPORT PendingScript
bool was_canceled,
bool is_external,
bool created_during_document_write,
- TimeTicks parser_blocking_load_start_time,
+ base::TimeTicks parser_blocking_load_start_time,
bool is_controlled_by_script_runner);
// |m_element| must points to the corresponding ScriptLoader's
@@ -162,7 +162,7 @@ class CORE_EXPORT PendingScript
Member<ScriptElementBase> element_;
TextPosition starting_position_; // Only used for inline script tags.
- TimeTicks parser_blocking_load_start_time_;
+ base::TimeTicks parser_blocking_load_start_time_;
ScriptSchedulingType scheduling_type_ = ScriptSchedulingType::kNotSet;
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/PRESUBMIT.py b/chromium/third_party/blink/renderer/core/script/resources/layered_api/PRESUBMIT.py
new file mode 100644
index 00000000000..4364aafa726
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/PRESUBMIT.py
@@ -0,0 +1,39 @@
+# 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.
+
+
+import sys
+
+
+def _CommonChecks(input_api, output_api):
+ results = []
+ # TODO(tkent): {kv-storage,toast,virtual-scroller}/.eslintrc.js specify babel-eslint parser, which
+ # is not in third_party/node/node_modules/.
+ mjs_files = input_api.AffectedFiles(
+ file_filter=lambda f: (f.LocalPath().endswith('.mjs') and
+ not '/virtual-scroller/' in f.LocalPath() and
+ not '/kv-storage/' in f.LocalPath() and
+ not '/toast/' in f.LocalPath()),
+ include_deletes=False)
+ if not mjs_files:
+ return results
+ try:
+ old_sys_path = sys.path[:]
+ cwd = input_api.PresubmitLocalPath()
+ sys.path += [input_api.os_path.join(cwd, '..', '..', '..', '..', '..',
+ '..', '..', 'tools')]
+ import web_dev_style.js_checker
+ checker = web_dev_style.js_checker.JSChecker(input_api, output_api)
+ results += checker.RunEsLintChecks(mjs_files)
+ finally:
+ sys.path = old_sys_path
+ return results
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return _CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return _CommonChecks(input_api, output_api)
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/README.md b/chromium/third_party/blink/renderer/core/script/resources/layered_api/README.md
index 270d8117aa5..479818efa35 100644
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/README.md
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/README.md
@@ -22,11 +22,27 @@ and commit these files together with the changes under resources/layered_api/.
## Which files are bundled
-All files under this directory will be included in the grdp and thus bundled
-in the Chromium binary, except for
+All files under
-- Files directly under `core/script/resources/layered_api`, or
-- Files starting with '.', 'README', or 'OWNERS'.
+- Sub-directories which have 'index.mjs' or
+- Directories of which last path component is 'internal'
+
+will be included in the grdp and thus bundled in the Chrome binary,
+except for files starting with '.', 'README', or 'OWNERS'.
So be careful about binary size increase when you add new files or add more
contents to existing files.
+
+## What are exposed
+
+All bundled resources are mapped to `std-internal://path-relative-to-here`, and
+`std-internal:` resources are not accessible from the web. Resources loaded as
+`std-internal:` can import other `std-internal:` resources.
+
+For example, `layered_api/foo/bar/baz.mjs` is mapped to
+`std-internal://foo/bar/baz.mjs`.
+
+All `index.mjs` resources are mapped to `std:directory-name-relative-to-here`
+too, and they are web-exposed. For example,
+`layered_api/elements/toast/index.mjs` is mapped to `std:elements/toast` as
+well as `std-internal://elements/toast/index.mjs`.
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/internal/reflection.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/internal/reflection.mjs
new file mode 100644
index 00000000000..989a4aa1ff1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/internal/reflection.mjs
@@ -0,0 +1,63 @@
+// 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.
+
+/**
+ * @file Manage attribute-property reflections.
+ * https://html.spec.whatwg.org/C/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes
+ */
+
+/**
+ * Add a bool reflection property to the specified prototype for the specified
+ * attribute.
+ *
+ * @param {!Object} proto An element prototype
+ * @param {string} attrName An attribute name
+ * @param {string} propName An optional property name. attrName will be used if
+ * this argument is omitted.
+ */
+export function installBool(proto, attrName, propName = attrName) {
+ let getter = function() {
+ return this.hasAttribute(attrName);
+ };
+ let setter = function(value) {
+ this.toggleAttribute(attrName, Boolean(value));
+ };
+ Object.defineProperty(
+ getter, 'name',
+ {configurable: true, enumerable: false, value: 'get ' + propName});
+ Object.defineProperty(
+ setter, 'name',
+ {configurable: true, enumerable: false, value: 'set ' + propName});
+ Object.defineProperty(
+ proto, propName,
+ {configurable: true, enumerable: true, get: getter, set: setter});
+}
+
+/**
+ * Add a DOMString reflection property to the specified prototype for the
+ * specified attribute.
+ *
+ * @param {!Element} element An element prototype
+ * @param {string} attrName An attribute name
+ * @param {string} propName An optional property name. attrName will be used if
+ * this argument is omitted.
+ */
+export function installString(proto, attrName, propName = attrName) {
+ let getter = function() {
+ let value = this.getAttribute(attrName);
+ return value === null ? '' : value;
+ };
+ let setter = function(value) {
+ this.setAttribute(attrName, value);
+ };
+ Object.defineProperty(
+ getter, 'name',
+ {configurable: true, enumerable: false, value: 'get ' + propName});
+ Object.defineProperty(
+ setter, 'name',
+ {configurable: true, enumerable: false, value: 'set ' + propName});
+ Object.defineProperty(
+ proto, propName,
+ {configurable: true, enumerable: true, get: getter, set: setter});
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/README.md b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/README.md
new file mode 100644
index 00000000000..c8962f767cb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/README.md
@@ -0,0 +1,3 @@
+# Switch control element
+
+https://github.com/tkent-google/std-switch/blob/master/README.md
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs
new file mode 100644
index 00000000000..8db1f4177ff
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs
@@ -0,0 +1,75 @@
+// 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.
+
+/**
+ * @file Utilities for form-associated custom elements
+ */
+
+import * as reflection from '../internal/reflection.mjs';
+
+function installGetter(proto, propName, getter) {
+ Object.defineProperty(
+ getter, 'name',
+ {configurable: true, enumerable: false, value: 'get ' + propName});
+ Object.defineProperty(
+ proto, propName, {configurable: true, enumerable: true, get: getter});
+}
+
+/**
+ * Add the following properties to |proto|.
+ * - disabled
+ * - name
+ * - type
+ * - form
+ * - willValidate
+ * - validity
+ * - validationMessage
+ * - labels
+ * - checkValidity()
+ * - reportValidity()
+ * - setCustomValidity(error)
+ *
+ * @param {!Object} proto An Element prototype which will have properties
+ * @param {!Symbol} internals A Symbol of the ElementInternals property of the
+ * element
+ */
+export function installPropertiesAndFunctions(proto, internals) {
+ reflection.installBool(proto, 'disabled');
+ reflection.installString(proto, 'name');
+ installGetter(proto, 'type', function() {
+ if (!(this instanceof proto.constructor)) {
+ throw TypeError(
+ 'The context object is not an instance of ' + proto.contructor.name);
+ }
+ return this.localName;
+ });
+
+ installGetter(proto, 'form', function() {
+ return this[internals].form;
+ });
+ installGetter(proto, 'willValidate', function() {
+ return this[internals].willValidate;
+ });
+ installGetter(proto, 'validity', function() {
+ return this[internals].validity;
+ });
+ installGetter(proto, 'validationMessage', function() {
+ return this[internals].validationMessage;
+ });
+ installGetter(proto, 'labels', function() {
+ return this[internals].labels;
+ });
+ proto.checkValidity = function() {
+ return this[internals].checkValidity();
+ };
+ proto.reportValidity = function() {
+ return this[internals].reportValidity();
+ };
+ proto.setCustomValidity = function(error) {
+ if (error === undefined) {
+ throw new TypeError('Too few arguments');
+ }
+ this[internals].setValidity({customError: true}, error);
+ };
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs
new file mode 100644
index 00000000000..6c7be3d46fc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs
@@ -0,0 +1,128 @@
+// 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.
+
+import * as face from './face_utils.mjs';
+import * as reflection from '../internal/reflection.mjs';
+import { SwitchTrack } from './track.mjs';
+import * as style from './style.mjs';
+
+// https://github.com/tkent-google/std-switch/issues/2
+const STATE_ATTR = 'on';
+
+// Private property symbols
+// TODO(tkent): Use private fields.
+const _internals = Symbol();
+const _track = Symbol();
+const _rippleElement = Symbol();
+const _containerElement = Symbol();
+
+export class StdSwitchElement extends HTMLElement {
+ // TODO(tkent): The following should be |static fooBar = value;|
+ // after enabling babel-eslint.
+ static get formAssociated() {
+ return true;
+ }
+ static get observedAttributes() {
+ return [STATE_ATTR];
+ }
+
+ constructor() {
+ super();
+ if (new.target !== StdSwitchElement) {
+ throw new TypeError('Illegal constructor: StdSwitchElement is not ' +
+ 'extensible for now');
+ }
+ this[_internals] = this.attachInternals();
+ this._initializeDOM();
+
+ this.addEventListener('click', this._onClick);
+ this.addEventListener('keypress', this._onKeyPress);
+ }
+
+ attributeChangedCallback(attrName, oldValue, newValue) {
+ if (attrName == STATE_ATTR) {
+ this[_track].value = newValue !== null;
+ // TODO(tkent): We should not add aria-checked attribute.
+ // https://github.com/WICG/aom/issues/127
+ this.setAttribute('aria-checked', newValue !== null ? 'true' : 'false');
+ }
+ }
+
+ connectedCallback() {
+ // TODO(tkent): We should not add tabindex attribute.
+ // https://github.com/w3c/webcomponents/issues/762
+ if (!this.hasAttribute('tabindex')) {
+ this.setAttribute('tabindex', '0');
+ }
+
+ // TODO(tkent): We should not add role attribute.
+ // https://github.com/WICG/aom/issues/127
+ if (!this.hasAttribute('role')) {
+ this.setAttribute('role', 'switch');
+ }
+ }
+
+ // TODO(tkent): Make this private.
+ _initializeDOM() {
+ let factory = this.ownerDocument;
+ let root = this.attachShadow({mode: 'closed'});
+ this[_containerElement] = factory.createElement('span');
+ this[_containerElement].id = 'container';
+ // Shadow elements should be invisible for a11y technologies.
+ this[_containerElement].setAttribute('aria-hidden', 'true');
+ root.appendChild(this[_containerElement]);
+
+ this[_track] = new SwitchTrack(factory);
+ this[_containerElement].appendChild(this[_track].element);
+ this[_track].value = this.on;
+
+ let thumbElement = this[_containerElement].appendChild(factory.createElement('span'));
+ thumbElement.id = 'thumb';
+ thumbElement.part.add('thumb');
+
+ this[_rippleElement] = thumbElement.appendChild(factory.createElement('span'));
+ this[_rippleElement].id = 'ripple';
+
+ root.adoptedStyleSheets = [style.styleSheetFactory()()];
+ }
+
+ // TODO(tkent): Make this private.
+ _onClick(event) {
+ for (let element of this[_containerElement].querySelectorAll('*')) {
+ style.markTransition(element);
+ }
+ this.on = !this.on;
+ this.dispatchEvent(new Event('input', {bubbles: true}));
+ this.dispatchEvent(new Event('change', {bubbles: true}));
+ }
+
+ // TODO(tkent): Make this private.
+ _onKeyPress(event) {
+ if (event.code == 'Space') {
+ // Do not scroll the page.
+ event.preventDefault();
+ this._onClick(event);
+ }
+ }
+}
+
+reflection.installBool(StdSwitchElement.prototype, STATE_ATTR);
+reflection.installBool(
+ StdSwitchElement.prototype, 'default' + STATE_ATTR,
+ 'default' + STATE_ATTR.charAt(0).toUpperCase() + STATE_ATTR.substring(1));
+face.installPropertiesAndFunctions(StdSwitchElement.prototype, _internals);
+
+// This is necessary for anyObject.toString.call(switchInstance).
+Object.defineProperty(StdSwitchElement.prototype, Symbol.toStringTag, {
+ configurable: true,
+ enumerable: false,
+ value: 'StdSwitchElement',
+ writable: false
+});
+
+customElements.define('std-switch', StdSwitchElement);
+delete StdSwitchElement.formAssociated;
+delete StdSwitchElement.observedAttributes;
+delete StdSwitchElement.prototype.attributeChangedCallback;
+delete StdSwitchElement.prototype.connectedCallback;
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs
new file mode 100644
index 00000000000..6b0bc2eca78
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs
@@ -0,0 +1,224 @@
+// 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.
+
+// Style constant values.
+const COLOR_ON = '#0077FF';
+const TRACK_RADIUS = '13px';
+const TRACK_BORDER_WIDTH = '2px';
+const THUMB_HEIGHT = '22px';
+const THUMB_WIDTH = '22px';
+const THUMB_MARGIN_START = '2px';
+const THUMB_MARGIN_END = '2px';
+
+// Returns a function returning a CSSStyleSheet().
+// TODO(tkent): Share this stylesheet factory feature with elements/toast/.
+export function styleSheetFactory() {
+ let styleSheet;
+ return () => {
+ if (!styleSheet) {
+ styleSheet = new CSSStyleSheet();
+ styleSheet.replaceSync(`
+:host {
+ block-size: 26px;
+ border: none;
+ box-sizing: border-box;
+ display: inline-block;
+ inline-size: 54px;
+ user-select: none;
+ vertical-align: middle;
+}
+
+#container {
+ align-items: center;
+ block-size: 100%;
+ display: inline-flex;
+ inline-size: 100%;
+}
+
+#thumb {
+ background: white;
+ block-size: ${THUMB_HEIGHT};
+ border-radius: calc(${THUMB_HEIGHT} / 2);
+ border: 1px solid black;
+ box-sizing: border-box;
+ display: inline-block;
+ margin-inline-start: calc(-100% + ${THUMB_MARGIN_START});
+ inline-size: ${THUMB_WIDTH};
+}
+
+/* :host::part(thumb-transitioning) doesn't work. crbug.com/980506 */
+#thumb[part~="thumb-transitioning"] {
+ transition: all linear 0.1s;
+}
+
+:host([on]) #thumb {
+ border: 1px solid ${COLOR_ON};
+ margin-inline-start: calc(0px - ${THUMB_WIDTH} - ${THUMB_MARGIN_END});
+}
+
+#track {
+ block-size: 100%;
+ border-radius: ${TRACK_RADIUS};
+ border: ${TRACK_BORDER_WIDTH} solid #dddddd;
+ box-shadow: 0 0 0 1px #f8f8f8;
+ box-sizing: border-box;
+ display: inline-block;
+ inline-size: 100%;
+ overflow: hidden;
+ padding: 0px;
+}
+
+#trackFill {
+ background: ${COLOR_ON};
+ block-size: 100%;
+ border-radius: calc(${TRACK_RADIUS}) - ${TRACK_BORDER_WIDTH});
+ box-shadow: none;
+ box-sizing: border-box;
+ display: inline-block;
+ inline-size: 0%;
+ vertical-align: top;
+}
+
+#trackFill[part~="track-fill-transitioning"] {
+ transition: all linear 0.1s;
+}
+
+:host([on]) #track {
+ border: ${TRACK_BORDER_WIDTH} solid ${COLOR_ON};
+}
+
+:host(:focus) {
+ outline-offset: 4px;
+}
+
+:host(:focus) #track {
+ box-shadow: 0 0 0 2px #f8f8f8;
+}
+
+:host([on]:focus) #track {
+ box-shadow: 0 0 0 2px #dddddd;
+}
+
+:host(:focus) #thumb {
+ border: 2px solid black;
+}
+
+:host([on]:focus) #thumb {
+ border: 2px solid ${COLOR_ON};
+}
+
+:host(:not(:focus-visible):focus) {
+ outline: none;
+}
+
+:host(:not(:disabled):hover) #thumb {
+ inline-size: 26px;
+}
+
+:host([on]:not(:disabled):hover) #thumb {
+ margin-inline-start: calc(0px - 26px - ${THUMB_MARGIN_END});
+}
+
+:host(:active) #track {
+ background: #dddddd;
+}
+
+:host([on]:active) #track {
+ border: 2px solid #77bbff;
+ box-shadow: 0 0 0 2px #f8f8f8;
+}
+
+:host([on]:active) #trackFill {
+ background: #77bbff;
+}
+
+:host(:disabled) {
+ opacity: 0.38;
+}
+
+/*
+ * display:inline-block in the :host ruleset overrides 'hidden' handling
+ * by the user agent.
+ */
+:host([hidden]) {
+ display: none;
+}
+
+`);
+ }
+ return styleSheet;
+ };
+}
+
+/**
+ * @param {!Element} element
+ */
+function setupTransitionCounter(element) {
+ if (element.runningTransitions !== undefined) {
+ return;
+ }
+ element.runningTransitions = 0;
+ element.addEventListener('transitionrun', e => {
+ if (e.target === element) {
+ ++element.runningTransitions;
+ }
+ });
+ let handleEndOrCancel = e => {
+ // Need to check runningTransitions>0 due to superfluous transitioncancel
+ // events; crbug.com/979556.
+ if (e.target === element && element.runningTransitions > 0) {
+ --element.runningTransitions;
+ }
+ };
+ element.addEventListener('transitionend', handleEndOrCancel);
+ element.addEventListener('transitioncancel', handleEndOrCancel);
+}
+
+/**
+ * Add '$part-transitioning' part to the element, and remove it on 'transitionend'
+ * event or remove it immediately if the element has no transitions.
+ *
+ * TODO(tkent): We should apply custom state.
+ *
+ * @param {!Element} element
+ */
+export function markTransition(element) {
+ // Should check hasAttribute() to avoid creating a DOMTokenList instance.
+ if (!element.hasAttribute('part') || element.part.length < 1) {
+ return;
+ }
+
+ setupTransitionCounter(element);
+
+ const partName = element.part[0] + '-transitioning';
+ if (element.part.contains(partName)) {
+ return;
+ }
+ // The style with partName might have transitions, and might have no
+ // transitions. We need to add partName anyway because we have no other
+ // ways to check existence of transitions. Then, we need to remove
+ // partName because state change without markTransition() should have
+ // style without partName.
+ //
+ // We add partName in an animation frame, and continue to request
+ // animation frames until runningTransitions becomes 0. If the style with
+ // partName has no transitions, runningTransitions keeps 0, and the second
+ // animation frame removes partName.
+ window.requestAnimationFrame(() => {
+ element.part.add(partName);
+
+ // If the element has a transition, it must start on the rendering just
+ // after this rAF callback. So we check runningTransitions in the next
+ // frame.
+ const removeIfNoTransitions = () => {
+ // No transitions started, or all transitions were completed.
+ if (element.runningTransitions === 0) {
+ element.part.remove(partName);
+ } else {
+ window.requestAnimationFrame(removeIfNoTransitions);
+ }
+ };
+ window.requestAnimationFrame(removeIfNoTransitions);
+ });
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/track.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/track.mjs
new file mode 100644
index 00000000000..aa8fc00c3d1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/track.mjs
@@ -0,0 +1,74 @@
+// 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.
+
+// Private property symbols
+// TODO(tkent): Use private fields.
+const _value = Symbol();
+const _trackElement = Symbol();
+const _fillElement = Symbol();
+const _slotElement = Symbol();
+
+export class SwitchTrack {
+
+ /**
+ * @param {!Document} factory A factory for elements created for this track.
+ */
+ constructor(factory) {
+ this[_value] = false;
+ this._initializeDOM(factory);
+ }
+
+ /**
+ * @return {!Element}
+ */
+ get element() {
+ return this[_trackElement];
+ }
+
+ /**
+ * @param {Boolean} newValue
+ */
+ set value(newValue) {
+ let oldValue = this[_value];
+ this[_value] = Boolean(newValue);
+
+ let bar = this[_fillElement];
+ if (bar) {
+ bar.style.inlineSize = this[_value] ? '100%' : '0%';
+ if (oldValue != this[_value]) {
+ this._addSlot();
+ }
+ }
+ }
+
+ // TODO(tkent): Use private fields. #initializeDOM = factory => { ...};
+ /**
+ * @param {!Document} factory A factory for elements created for this track.
+ */
+ _initializeDOM(factory) {
+ this[_trackElement] = factory.createElement('div');
+ this[_trackElement].id = 'track';
+ this[_trackElement].part.add('track');
+ this[_fillElement] = factory.createElement('span');
+ this[_fillElement].id = 'trackFill';
+ this[_fillElement].part.add('track-fill');
+ this[_trackElement].appendChild(this[_fillElement]);
+ this[_slotElement] = factory.createElement('slot');
+ this._addSlot();
+ }
+
+ /**
+ * Add the <slot>
+ * - next to _fillElement if _value is true
+ * - as a child of _fillElement if _value is false
+ * This behavior is helpful to show text in the track.
+ */
+ _addSlot() {
+ if (this[_value]) {
+ this[_fillElement].appendChild(this[_slotElement]);
+ } else {
+ this[_trackElement].appendChild(this[_slotElement]);
+ }
+ }
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/.eslintrc.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/.eslintrc.js
new file mode 100644
index 00000000000..8f9a67630c4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/.eslintrc.js
@@ -0,0 +1,338 @@
+// 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.
+
+module.exports = {
+ root: true,
+ env: {
+ es6: true,
+ browser: true
+ },
+ 'parser': 'babel-eslint',
+ parserOptions: {
+ sourceType: 'module',
+ ecmaVersion: 2019
+ },
+ rules: {
+ 'for-direction': 'error',
+ 'getter-return': 'error',
+ 'no-async-promise-executor': 'error',
+ 'no-await-in-loop': 'error',
+ 'no-compare-neg-zero': 'error',
+ 'no-cond-assign': ['error', 'except-parens'],
+ 'no-console': 'error',
+ 'no-constant-condition': ['error', {checkLoops: false}],
+ 'no-control-regex': 'error',
+ 'no-debugger': 'error',
+ 'no-dupe-args': 'error',
+ 'no-dupe-keys': 'error',
+ 'no-duplicate-case': 'error',
+ 'no-empty': 'error',
+ 'no-empty-character-class': 'error',
+ 'no-ex-assign': 'error',
+ 'no-extra-boolean-cast': 'error',
+ 'no-extra-parens': [
+ 'error',
+ 'all',
+ {
+ conditionalAssign: false,
+ nestedBinaryExpressions: false,
+ returnAssign: false
+ }
+ ],
+ 'no-extra-semi': 'error',
+ 'no-func-assign': 'error',
+ 'no-inner-declarations': 'off',
+ 'no-invalid-regexp': 'error',
+ 'no-irregular-whitespace': 'error',
+ 'no-misleading-character-class': 'error',
+ 'no-obj-calls': 'error',
+ 'no-prototype-builtins': 'error',
+ 'no-regex-spaces': 'error',
+ 'no-sparse-arrays': 'error',
+ 'no-template-curly-in-string': 'error',
+ 'no-unexpected-multiline': 'error',
+ 'no-unreachable': 'error',
+ 'no-unsafe-finally': 'off',
+ 'no-unsafe-negation': 'error',
+ 'use-isnan': 'error',
+ 'valid-typeof': 'error',
+ 'accessor-pairs': 'error',
+ 'array-callback-return': 'error',
+ 'block-scoped-var': 'off',
+ 'class-methods-use-this': 'off',
+ 'complexity': 'off',
+ 'consistent-return': 'error',
+ 'curly': ['error', 'all'],
+ 'default-case': 'off',
+ 'dot-location': ['error', 'property'],
+ 'dot-notation': 'error',
+ 'eqeqeq': 'error',
+ 'guard-for-in': 'off',
+ 'no-alert': 'error',
+ 'no-caller': 'error',
+ 'no-case-declarations': 'error',
+ 'no-div-regex': 'off',
+ 'no-else-return': 'error',
+ 'no-empty-function': 'off',
+ 'no-empty-pattern': 'error',
+ 'no-eq-null': 'error',
+ 'no-eval': 'error',
+ 'no-extend-native': 'error',
+ 'no-extra-bind': 'error',
+ 'no-extra-label': 'error',
+ 'no-fallthrough': 'error',
+ 'no-floating-decimal': 'error',
+ 'no-global-assign': 'error',
+ 'no-implicit-coercion': 'error',
+ 'no-implicit-globals': 'error',
+ 'no-implied-eval': 'error',
+ 'no-invalid-this': 'error',
+ 'no-iterator': 'error',
+ 'no-labels': ['error', {allowLoop: true}],
+ 'no-lone-blocks': 'error',
+ 'no-loop-func': 'error',
+ 'no-magic-numbers': ['error', {ignore: [0, 1]}],
+ 'no-multi-spaces': ['error', {ignoreEOLComments: true}],
+ 'no-multi-str': 'error',
+ 'no-new': 'error',
+ 'no-new-func': 'error',
+ 'no-new-wrappers': 'error',
+ 'no-octal': 'error',
+ 'no-octal-escape': 'error',
+ 'no-param-reassign': 'off',
+ 'no-process-env': 'error',
+ 'no-proto': 'error',
+ 'no-redeclare': 'error',
+ 'no-restricted-properties': 'off',
+ 'no-return-assign': ['error', 'except-parens'],
+ 'no-return-await': 'error',
+ 'no-script-url': 'off',
+ 'no-self-assign': 'error',
+ 'no-self-compare': 'error',
+ 'no-sequences': 'error',
+ 'no-throw-literal': 'error',
+ 'no-unmodified-loop-condition': 'error',
+ 'no-unused-expressions': 'error',
+ 'no-unused-labels': 'error',
+ 'no-useless-call': 'error',
+ 'no-useless-concat': 'error',
+ 'no-useless-escape': 'error',
+ 'no-useless-return': 'error',
+ 'no-void': 'error',
+ 'no-warning-comments': 'off',
+ 'no-with': 'error',
+ 'prefer-promise-reject-errors': 'error',
+ 'radix': ['error', 'as-needed'],
+ 'require-await': 'off',
+ 'vars-on-top': 'off',
+ 'wrap-iife': ['error', 'outside'],
+ 'yoda': ['error', 'never'],
+ 'strict': ['error', 'global'],
+ 'init-declarations': 'off',
+ 'no-delete-var': 'error',
+ 'no-label-var': 'error',
+ 'no-restricted-globals': 'off',
+ 'no-shadow': 'error',
+ 'no-shadow-restricted-names': 'error',
+ 'no-undef': 'error',
+ 'no-undef-init': 'error',
+ 'no-undefined': 'off',
+ 'no-unused-vars': 'error',
+ 'no-use-before-define': ['error', 'nofunc'],
+ 'callback-return': 'off',
+ 'global-require': 'error',
+ 'handle-callback-err': 'error',
+ 'no-buffer-constructor': 'error',
+ 'no-mixed-requires': ['error', true],
+ 'no-new-require': 'error',
+ 'no-path-concat': 'error',
+ 'no-process-exit': 'error',
+ 'no-restricted-modules': 'off',
+ 'no-sync': 'off',
+ 'array-bracket-newline': ['error', {multiline: true}],
+ 'array-bracket-spacing': ['error', 'never'],
+ 'array-element-newline': 'off',
+ 'block-spacing': ['error', 'always'],
+ 'brace-style': [
+ 'error',
+ '1tbs',
+ {allowSingleLine: false}
+ ],
+ camelcase: ['error', {properties: 'always'}],
+ 'capitalized-comments': 'off',
+ 'comma-dangle': ['error', 'always-multiline'],
+ 'comma-spacing': [
+ 'error',
+ {
+ before: false,
+ after: true
+ }
+ ],
+ 'comma-style': ['error', 'last'],
+ 'computed-property-spacing': ['error', 'never'],
+ 'consistent-this': 'off',
+ 'eol-last': 'error',
+ 'func-call-spacing': ['error', 'never'],
+ 'func-name-matching': 'error',
+ 'func-names': 'off',
+ 'func-style': ['error', 'declaration'],
+ 'function-paren-newline': 'off',
+ 'id-blacklist': 'off',
+ 'id-length': 'off',
+ 'id-match': 'off',
+ indent: 'off', // not really compatible with clang-format
+ 'jsx-quotes': 'off',
+ 'key-spacing': [
+ 'error',
+ {
+ beforeColon: false,
+ afterColon: true,
+ mode: 'strict'
+ }
+ ],
+ 'keyword-spacing': [
+ 'error',
+ {
+ before: true,
+ after: true
+ }
+ ],
+ 'line-comment-position': 'off',
+ 'linebreak-style': ['error', 'unix'],
+ 'lines-around-comment': 'off',
+ 'max-depth': 'off',
+ 'max-len': 'off',
+ 'max-lines': 'off',
+ 'max-nested-callbacks': 'off',
+ 'max-params': 'off',
+ 'max-statements': 'off',
+ 'max-statements-per-line': ['error', {max: 1}],
+ 'multiline-ternary': ['error', 'always-multiline'],
+ 'new-cap': 'error',
+ 'new-parens': 'error',
+ 'newline-per-chained-call': 'off',
+ 'no-array-constructor': 'error',
+ 'no-bitwise': 'off',
+ 'no-continue': 'off',
+ 'no-inline-comments': 'off',
+ 'no-lonely-if': 'error',
+ 'no-mixed-operators': [
+ 'error',
+ {
+ groups: [
+ ['&', '|', '^', '~', '<<', '>>', '>>>'],
+ ['==', '!=', '===', '!==', '>', '>=', '<', '<='],
+ ['&&', '||'],
+ ['in', 'instanceof']
+ ]
+ }
+ ],
+ 'no-mixed-spaces-and-tabs': 'error',
+ 'no-multi-assign': 'off',
+ 'no-multiple-empty-lines': 'error',
+ 'no-negated-condition': 'off',
+ 'no-nested-ternary': 'error',
+ 'no-new-object': 'error',
+ 'no-plusplus': 'off',
+ 'no-restricted-syntax': 'off',
+ 'no-tabs': 'error',
+ 'no-ternary': 'off',
+ 'no-trailing-spaces': 'error',
+ 'no-underscore-dangle': 'off',
+ 'no-unneeded-ternary': 'error',
+ 'no-whitespace-before-property': 'error',
+ 'nonblock-statement-body-position': 'error',
+ 'object-curly-newline': ['error', {consistent: true}],
+ 'object-curly-spacing': ['error', 'never'],
+ 'object-property-newline': 'off',
+ 'one-var': ['error', 'never'],
+ 'one-var-declaration-per-line': ['error', 'initializations'],
+ 'operator-assignment': ['error', 'always'],
+ 'operator-linebreak': ['error', 'after'],
+ 'padded-blocks': ['error', 'never'],
+ 'padding-line-between-statements': 'off',
+ 'quote-props': ['error', 'as-needed'],
+ quotes: [
+ 'error',
+ 'single',
+ {
+ avoidEscape: true,
+ allowTemplateLiterals: true
+ }
+ ],
+ semi: ['error', 'always'],
+ 'semi-spacing': 'error',
+ 'semi-style': 'error',
+ 'sort-keys': 'off',
+ 'sort-vars': 'off',
+ 'space-before-blocks': ['error', 'always'],
+ 'space-before-function-paren': [
+ 'error',
+ {
+ anonymous: 'always',
+ named: 'never'
+ }
+ ],
+ 'space-in-parens': ['error', 'never'],
+ 'space-infix-ops': 'error',
+ 'space-unary-ops': [
+ 'error',
+ {
+ words: true,
+ nonwords: false
+ }
+ ],
+ 'spaced-comment': ['error', 'always'],
+ 'switch-colon-spacing': 'error',
+ 'template-tag-spacing': 'error',
+ 'unicode-bom': 'error',
+ 'wrap-regex': 'off',
+ 'arrow-body-style': 'off',
+ 'arrow-parens': ['error', 'as-needed'],
+ 'arrow-spacing': 'error',
+ 'constructor-super': 'error',
+ 'generator-star-spacing': ['error', 'neither'],
+ 'no-class-assign': 'error',
+ 'no-confusing-arrow': 'off',
+ 'no-const-assign': 'error',
+ 'no-dupe-class-members': 'error',
+ 'no-duplicate-imports': 'error',
+ 'no-new-symbol': 'error',
+ 'no-restricted-imports': 'off',
+ 'no-this-before-super': 'error',
+ 'no-useless-computed-key': 'error',
+ 'no-useless-constructor': 'error',
+ 'no-useless-rename': 'error',
+ 'no-var': 'error',
+ 'object-shorthand': 'error',
+ 'prefer-arrow-callback': 'error',
+ 'prefer-const': ['error', {ignoreReadBeforeAssign: true}],
+ 'prefer-destructuring': [
+ 'error',
+ {
+ VariableDeclarator: {
+ array: false,
+ object: true
+ },
+ AssignmentExpression: {
+ array: false,
+ object: false
+ }
+ },
+ {
+ enforceForRenamedProperties: false
+ }
+ ],
+ 'prefer-numeric-literals': 'error',
+ 'prefer-rest-params': 'error',
+ 'prefer-spread': 'error',
+ 'prefer-template': 'off',
+ 'require-yield': 'error',
+ 'rest-spread-spacing': 'error',
+ 'sort-imports': 'off',
+ 'symbol-description': 'error',
+ 'template-curly-spacing': ['error', 'never'],
+ 'yield-star-spacing': ['error', 'after']
+ }
+};
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/OWNERS b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/OWNERS
new file mode 100644
index 00000000000..d76cdfa11f0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/OWNERS
@@ -0,0 +1 @@
+fergal@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/index.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/index.mjs
new file mode 100644
index 00000000000..69232f8475a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/index.mjs
@@ -0,0 +1,280 @@
+/**
+ * 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.
+ *
+ * @fileoverview This file defines the class for the Standard Toast LAPI
+ * and the accompanying showToast() function.
+ * EXPLAINER: https://github.com/jackbsteinberg/std-toast
+ * TEST PATH: /chromium/src/third_party/blink/web_tests/external/wpt/std-toast/*
+ * @package
+ */
+
+import * as reflection from '../internal/reflection.mjs';
+
+const DEFAULT_DURATION = 3000;
+const TYPES = new Set(['success', 'warning', 'error']);
+
+function stylesheetFactory() {
+ let stylesheet;
+ return function generate() {
+ if (!stylesheet) {
+ stylesheet = new CSSStyleSheet();
+ stylesheet.replaceSync(`
+ :host {
+ position: fixed;
+ bottom: 1em;
+ right: 1em;
+ border: solid;
+ padding: 1em;
+ background: white;
+ color: black;
+ z-index: 1;
+ }
+
+ :host(:not([open])) {
+ display: none;
+ }
+
+ .default-closebutton {
+ user-select: none;
+ }
+
+ :host([type=success i]) {
+ border-color: green;
+ }
+
+ :host([type=warning i]) {
+ border-color: orange;
+ }
+
+ :host([type=error i]) {
+ border-color: red;
+ }
+ `);
+ // TODO(jacksteinberg): use offset-block-end: / offset-inline-end: over bottom: / right:
+ // when implemented https://bugs.chromium.org/p/chromium/issues/detail?id=538475
+ }
+ return stylesheet;
+ };
+}
+
+const generateStylesheet = stylesheetFactory();
+
+export class StdToastElement extends HTMLElement {
+ static observedAttributes = ['open', 'closebutton'];
+ #shadow = this.attachShadow({mode: 'closed'});
+ #timeoutID;
+ #actionSlot;
+ #closeButtonElement;
+ #setCloseTimeout = duration => {
+ clearTimeout(this.#timeoutID);
+
+ if (duration === Infinity) {
+ this.#timeoutID = null;
+ } else {
+ this.#timeoutID = setTimeout(() => {
+ this.removeAttribute('open');
+ }, duration);
+ }
+ };
+
+ constructor(message) {
+ super();
+
+ this.#shadow.adoptedStyleSheets = [generateStylesheet()];
+
+ this.#shadow.appendChild(document.createElement('slot'));
+
+ this.#actionSlot = document.createElement('slot');
+ this.#actionSlot.setAttribute('name', 'action');
+ this.#shadow.appendChild(this.#actionSlot);
+
+ this.#closeButtonElement = document.createElement('button');
+ this.#closeButtonElement.setAttribute('part', 'closebutton');
+ setDefaultCloseButton(this.#closeButtonElement);
+ this.#shadow.appendChild(this.#closeButtonElement);
+
+ this.#closeButtonElement.addEventListener('click', () => {
+ this.hide();
+ });
+
+ if (message !== undefined) {
+ this.textContent = message;
+ }
+ }
+
+ connectedCallback() {
+ if (!this.hasAttribute('role')) {
+ this.setAttribute('role', 'status');
+ }
+ // TODO(jacksteinberg): use https://github.com/whatwg/html/pull/4658 when implemented
+ }
+
+ get action() {
+ return this.#actionSlot.assignedNodes().length !== 0 ?
+ this.#actionSlot.assignedNodes()[0] :
+ null;
+ }
+
+ set action(val) {
+ const previousAction = this.action;
+ if (val !== null) {
+ if (!isElement(val)) {
+ throw new TypeError('Invalid argument: must be type Element');
+ }
+
+ val.setAttribute('slot', 'action');
+ this.insertBefore(val, previousAction);
+ }
+
+ if (previousAction !== null) {
+ previousAction.remove();
+ }
+ }
+
+ get closeButton() {
+ if (this.hasAttribute('closebutton')) {
+ const closeAttr = this.getAttribute('closebutton');
+ return closeAttr === '' ? true : closeAttr;
+ }
+ return false;
+ }
+
+ set closeButton(val) {
+ if (val === true) {
+ this.setAttribute('closebutton', '');
+ } else if (val === false) {
+ this.removeAttribute('closebutton');
+ } else {
+ this.setAttribute('closebutton', val);
+ }
+ }
+
+ get type() {
+ const typeAttr = this.getAttribute('type');
+ if (typeAttr === null) {
+ return '';
+ }
+
+ const typeAttrLower = typeAttr.toLowerCase();
+
+ if (TYPES.has(typeAttrLower)) {
+ return typeAttrLower;
+ }
+
+ return '';
+ }
+
+ set type(val) {
+ this.setAttribute('type', val);
+ }
+
+ show({duration = DEFAULT_DURATION} = {}) {
+ if (duration <= 0) {
+ throw new RangeError(`Invalid Argument: duration must be greater than 0 [${duration} given]`);
+ }
+
+ this.setAttribute('open', '');
+ this.#setCloseTimeout(duration);
+ }
+
+ hide() {
+ this.removeAttribute('open');
+ }
+
+ toggle(force) {
+ this.toggleAttribute('open', force);
+ }
+
+ attributeChangedCallback(name, oldValue, newValue) {
+ switch (name) {
+ case 'open':
+ if (newValue !== null && oldValue === null) {
+ this.dispatchEvent(new Event('show'));
+ } else if (newValue === null) {
+ this.dispatchEvent(new Event('hide'));
+ this.#setCloseTimeout(Infinity);
+ }
+ break;
+ case 'closebutton':
+ if (newValue !== null) {
+ if (newValue === '') {
+ setDefaultCloseButton(this.#closeButtonElement);
+ } else {
+ replaceDefaultCloseButton(this.#closeButtonElement, newValue);
+ }
+ }
+ // if newValue === null we do nothing, since CSS will hide the button
+ break;
+ }
+ }
+}
+
+reflection.installBool(StdToastElement.prototype, 'open');
+
+customElements.define('std-toast', StdToastElement);
+
+delete StdToastElement.prototype.attributeChangedCallback;
+delete StdToastElement.prototype.observedAttributes;
+delete StdToastElement.prototype.connectedCallback;
+
+export function showToast(message, options = {}) {
+ const toast = new StdToastElement(message);
+
+ const {
+ action,
+ closeButton,
+ type,
+ ...showOptions
+ } = options;
+
+ if (isElement(action)) {
+ toast.action = action;
+ } else if (action !== undefined) {
+ const actionButton = document.createElement('button');
+
+ // Unlike String(), this performs the desired JavaScript ToString operation.
+ // https://gist.github.com/domenic/82adbe7edc4a33a70f42f255479cec39
+ actionButton.textContent = `${action}`;
+
+ actionButton.setAttribute('slot', 'action');
+ toast.appendChild(actionButton);
+ }
+
+ if (closeButton !== undefined) {
+ toast.closeButton = closeButton;
+ }
+
+ if (type !== undefined) {
+ toast.type = type;
+ }
+
+ document.body.append(toast);
+ toast.show(showOptions);
+
+ return toast;
+}
+
+const idGetter =
+ Object.getOwnPropertyDescriptor(Element.prototype, 'id').get;
+function isElement(value) {
+ try {
+ idGetter.call(value);
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+function setDefaultCloseButton(closeButton) {
+ closeButton.setAttribute('aria-label', 'close');
+ closeButton.setAttribute('class', 'default-closebutton');
+ closeButton.textContent = '×';
+}
+
+function replaceDefaultCloseButton(closeButton, value) {
+ closeButton.textContent = value;
+ closeButton.removeAttribute('aria-label');
+ closeButton.removeAttribute('class');
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/.eslintrc.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/.eslintrc.js
new file mode 100644
index 00000000000..90e626a41fc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/.eslintrc.js
@@ -0,0 +1,337 @@
+// 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.
+
+module.exports = {
+ root: true,
+ env: {
+ es6: true,
+ browser: true
+ },
+ 'parser': 'babel-eslint',
+ parserOptions: {
+ sourceType: 'module',
+ ecmaVersion: 2019
+ },
+ rules: {
+ 'for-direction': 'error',
+ 'getter-return': 'error',
+ 'no-async-promise-executor': 'error',
+ 'no-await-in-loop': 'error',
+ 'no-compare-neg-zero': 'error',
+ 'no-cond-assign': ['error', 'except-parens'],
+ 'no-console': 'error',
+ 'no-constant-condition': ['error', {checkLoops: false}],
+ 'no-control-regex': 'error',
+ 'no-debugger': 'error',
+ 'no-dupe-args': 'error',
+ 'no-dupe-keys': 'error',
+ 'no-duplicate-case': 'error',
+ 'no-empty': 'error',
+ 'no-empty-character-class': 'error',
+ 'no-ex-assign': 'error',
+ 'no-extra-boolean-cast': 'error',
+ 'no-extra-parens': [
+ 'error',
+ 'all',
+ {
+ conditionalAssign: false,
+ nestedBinaryExpressions: false,
+ returnAssign: false
+ }
+ ],
+ 'no-extra-semi': 'error',
+ 'no-func-assign': 'error',
+ 'no-inner-declarations': 'off',
+ 'no-invalid-regexp': 'error',
+ 'no-irregular-whitespace': 'error',
+ 'no-misleading-character-class': 'error',
+ 'no-obj-calls': 'error',
+ 'no-prototype-builtins': 'error',
+ 'no-regex-spaces': 'error',
+ 'no-sparse-arrays': 'error',
+ 'no-template-curly-in-string': 'error',
+ 'no-unexpected-multiline': 'error',
+ 'no-unreachable': 'error',
+ 'no-unsafe-finally': 'off',
+ 'no-unsafe-negation': 'error',
+ 'use-isnan': 'error',
+ 'valid-typeof': 'error',
+ 'accessor-pairs': 'error',
+ 'array-callback-return': 'error',
+ 'block-scoped-var': 'off',
+ 'class-methods-use-this': 'off',
+ 'complexity': 'off',
+ 'consistent-return': 'error',
+ 'curly': ['error', 'all'],
+ 'default-case': 'off',
+ 'dot-location': ['error', 'property'],
+ 'dot-notation': 'error',
+ 'eqeqeq': 'error',
+ 'guard-for-in': 'off',
+ 'no-alert': 'error',
+ 'no-caller': 'error',
+ 'no-case-declarations': 'error',
+ 'no-div-regex': 'off',
+ 'no-empty-function': 'off',
+ 'no-empty-pattern': 'error',
+ 'no-eq-null': 'error',
+ 'no-eval': 'error',
+ 'no-extend-native': 'error',
+ 'no-extra-bind': 'error',
+ 'no-extra-label': 'error',
+ 'no-fallthrough': 'error',
+ 'no-floating-decimal': 'error',
+ 'no-global-assign': 'error',
+ 'no-implicit-coercion': 'error',
+ 'no-implicit-globals': 'error',
+ 'no-implied-eval': 'error',
+ 'no-iterator': 'error',
+ 'no-labels': ['error', {allowLoop: true}],
+ 'no-lone-blocks': 'error',
+ 'no-loop-func': 'error',
+ 'no-magic-numbers': ['error', {ignore: [0, 1, 2]}],
+ 'no-multi-spaces': ['error', {ignoreEOLComments: true}],
+ 'no-multi-str': 'error',
+ 'no-new': 'error',
+ 'no-new-func': 'error',
+ 'no-new-wrappers': 'error',
+ 'no-octal': 'error',
+ 'no-octal-escape': 'error',
+ 'no-param-reassign': 'off',
+ 'no-process-env': 'error',
+ 'no-proto': 'error',
+ 'no-redeclare': 'error',
+ 'no-restricted-properties': 'off',
+ 'no-return-assign': ['error', 'except-parens'],
+ 'no-return-await': 'error',
+ 'no-script-url': 'off',
+ 'no-self-assign': 'error',
+ 'no-self-compare': 'error',
+ 'no-sequences': 'error',
+ 'no-throw-literal': 'error',
+ 'no-unmodified-loop-condition': 'error',
+ 'no-unused-expressions': 'error',
+ 'no-unused-labels': 'error',
+ 'no-useless-call': 'error',
+ 'no-useless-concat': 'error',
+ 'no-useless-escape': 'error',
+ 'no-useless-return': 'error',
+ 'no-void': 'error',
+ 'no-warning-comments': 'off',
+ 'no-with': 'error',
+ 'prefer-promise-reject-errors': 'error',
+ 'radix': ['error', 'as-needed'],
+ 'require-await': 'off',
+ 'vars-on-top': 'off',
+ 'wrap-iife': ['error', 'outside'],
+ 'yoda': ['error', 'never'],
+ 'strict': ['error', 'global'],
+ 'init-declarations': 'off',
+ 'no-delete-var': 'error',
+ 'no-label-var': 'error',
+ 'no-restricted-globals': 'off',
+ 'no-shadow': 'error',
+ 'no-shadow-restricted-names': 'error',
+ 'no-undef': 'error',
+ 'no-undef-init': 'error',
+ 'no-undefined': 'off',
+ 'no-unused-vars': 'error',
+ 'no-use-before-define': ['error', 'nofunc'],
+ 'callback-return': 'off',
+ 'global-require': 'error',
+ 'handle-callback-err': 'error',
+ 'no-buffer-constructor': 'error',
+ 'no-mixed-requires': ['error', true],
+ 'no-new-require': 'error',
+ 'no-path-concat': 'error',
+ 'no-process-exit': 'error',
+ 'no-restricted-modules': 'off',
+ 'no-sync': 'off',
+ 'array-bracket-newline': ['error', {multiline: true}],
+ 'array-bracket-spacing': ['error', 'never'],
+ 'array-element-newline': 'off',
+ 'block-spacing': ['error', 'always'],
+ 'brace-style': [
+ 'error',
+ '1tbs',
+ {allowSingleLine: false}
+ ],
+ camelcase: ['error', {properties: 'always'}],
+ 'capitalized-comments': 'off',
+ 'comma-dangle': ['error', 'always-multiline'],
+ 'comma-spacing': [
+ 'error',
+ {
+ before: false,
+ after: true
+ }
+ ],
+ 'comma-style': ['error', 'last'],
+ 'computed-property-spacing': ['error', 'never'],
+ 'consistent-this': 'off',
+ 'eol-last': 'error',
+ 'func-call-spacing': ['error', 'never'],
+ 'func-name-matching': 'error',
+ 'func-names': 'off',
+ 'func-style': ['error', 'declaration'],
+ 'function-paren-newline': 'off',
+ 'id-blacklist': 'off',
+ 'id-length': 'off',
+ 'id-match': 'off',
+ indent: 'off', // not really compatible with clang-format
+ 'jsx-quotes': 'off',
+ 'key-spacing': [
+ 'error',
+ {
+ beforeColon: false,
+ afterColon: true,
+ mode: 'strict'
+ }
+ ],
+ 'keyword-spacing': [
+ 'error',
+ {
+ before: true,
+ after: true
+ }
+ ],
+ 'line-comment-position': 'off',
+ 'linebreak-style': ['error', 'unix'],
+ 'lines-around-comment': 'off',
+ 'max-depth': 'off',
+ 'max-len': ['error', {
+ tabWidth: 2,
+ ignorePattern: "(^import |// eslint-disable-line )"}],
+ 'max-lines': 'off',
+ 'max-nested-callbacks': 'off',
+ 'max-params': 'off',
+ 'max-statements': 'off',
+ 'max-statements-per-line': ['error', {max: 1}],
+ 'multiline-ternary': ['error', 'always-multiline'],
+ 'new-cap': 'error',
+ 'new-parens': 'error',
+ 'newline-per-chained-call': 'off',
+ 'no-array-constructor': 'error',
+ 'no-bitwise': 'off',
+ 'no-continue': 'off',
+ 'no-inline-comments': 'off',
+ 'no-mixed-operators': [
+ 'error',
+ {
+ groups: [
+ ['&', '|', '^', '~', '<<', '>>', '>>>'],
+ ['==', '!=', '===', '!==', '>', '>=', '<', '<='],
+ ['&&', '||'],
+ ['in', 'instanceof']
+ ]
+ }
+ ],
+ 'no-mixed-spaces-and-tabs': 'error',
+ 'no-multi-assign': 'off',
+ 'no-multiple-empty-lines': 'error',
+ 'no-negated-condition': 'off',
+ 'no-nested-ternary': 'error',
+ 'no-new-object': 'error',
+ 'no-plusplus': 'off',
+ 'no-restricted-syntax': 'off',
+ 'no-tabs': 'error',
+ 'no-ternary': 'off',
+ 'no-trailing-spaces': 'error',
+ 'no-underscore-dangle': 'off',
+ 'no-unneeded-ternary': 'error',
+ 'no-whitespace-before-property': 'error',
+ 'nonblock-statement-body-position': 'error',
+ 'object-curly-newline': ['error', {consistent: true}],
+ 'object-curly-spacing': ['error', 'never'],
+ 'object-property-newline': 'off',
+ 'one-var': ['error', 'never'],
+ 'one-var-declaration-per-line': ['error', 'initializations'],
+ 'operator-assignment': ['error', 'always'],
+ 'operator-linebreak': ['error', 'after'],
+ 'padded-blocks': ['error', 'never'],
+ 'padding-line-between-statements': 'off',
+ 'quote-props': ['error', 'as-needed'],
+ quotes: [
+ 'error',
+ 'single',
+ {
+ avoidEscape: true,
+ allowTemplateLiterals: true
+ }
+ ],
+ semi: ['error', 'always'],
+ 'semi-spacing': 'error',
+ 'semi-style': 'error',
+ 'sort-keys': 'off',
+ 'sort-vars': 'off',
+ 'space-before-blocks': ['error', 'always'],
+ 'space-before-function-paren': [
+ 'error',
+ {
+ anonymous: 'always',
+ named: 'never'
+ }
+ ],
+ 'space-in-parens': ['error', 'never'],
+ 'space-infix-ops': 'error',
+ 'space-unary-ops': [
+ 'error',
+ {
+ words: true,
+ nonwords: false
+ }
+ ],
+ 'spaced-comment': ['error', 'always'],
+ 'switch-colon-spacing': 'error',
+ 'template-tag-spacing': 'error',
+ 'unicode-bom': 'error',
+ 'wrap-regex': 'off',
+ 'arrow-body-style': 'off',
+ 'arrow-parens': ['error', 'as-needed'],
+ 'arrow-spacing': 'error',
+ 'constructor-super': 'error',
+ 'generator-star-spacing': ['error', 'neither'],
+ 'no-class-assign': 'error',
+ 'no-confusing-arrow': 'off',
+ 'no-const-assign': 'error',
+ 'no-dupe-class-members': 'error',
+ 'no-duplicate-imports': 'error',
+ 'no-new-symbol': 'error',
+ 'no-restricted-imports': 'off',
+ 'no-this-before-super': 'error',
+ 'no-useless-computed-key': 'error',
+ 'no-useless-constructor': 'error',
+ 'no-useless-rename': 'error',
+ 'no-var': 'error',
+ 'object-shorthand': 'error',
+ 'prefer-arrow-callback': 'error',
+ 'prefer-const': ['error', {ignoreReadBeforeAssign: true}],
+ 'prefer-destructuring': [
+ 'error',
+ {
+ VariableDeclarator: {
+ array: false,
+ object: true
+ },
+ AssignmentExpression: {
+ array: false,
+ object: false
+ }
+ },
+ {
+ enforceForRenamedProperties: false
+ }
+ ],
+ 'prefer-numeric-literals': 'error',
+ 'prefer-rest-params': 'error',
+ 'prefer-spread': 'error',
+ 'prefer-template': 'off',
+ 'require-yield': 'error',
+ 'rest-spread-spacing': 'error',
+ 'sort-imports': 'off',
+ 'symbol-description': 'error',
+ 'template-curly-spacing': ['error', 'never'],
+ 'yield-star-spacing': ['error', 'after']
+ }
+};
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/OWNERS b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/OWNERS
new file mode 100644
index 00000000000..d76cdfa11f0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/OWNERS
@@ -0,0 +1 @@
+fergal@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/docs/README.md b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/docs/README.md
new file mode 100644
index 00000000000..c5ea6fc86c3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/docs/README.md
@@ -0,0 +1,297 @@
+# Virtual Scroller Notes
+
+This is Blink's implementation of the [`<virtual-scroller>`](https://github.com/WICG/virtual-scroller) element.
+
+## Status
+
+This is a prototype with many known issues.
+
+## Principles
+
+- Avoid operations that are O(number of children)
+- Ensure that we only perform operations that cause DOM, style or rendering work in the browser
+ that is O(number of visible elements).
+- Avoid forcing layout from JS.
+
+## Current Implementation Strategy
+
+The prototype uses a custom element implemented in JS.
+It only handles vertical block layout,
+so this talks only about height.
+This custom element manages the display-locking status of its child items.
+It considers a range of pixels to be the "unlocked range".
+This range is determined from the window size.
+
+TODO(crbug.com/983052): Be smarter about determining the buffer size,
+given that the window can be resized.
+
+Items which are within the unlocked range are left unlocked.
+All other items are locked
+so that they do not incur style and rendering costs for their contents.
+They are locked with a height that is our best guess at their rendered height.
+This guess is based on
+- a fixed default
+- a previously measured height of this item
+- an average of previous observed heights of items
+
+The virtual scroller listens to observers to know when it needs to reconsider which items should be locked.
+It keeps a resize observer on itself since if it is resized,
+items may need to be newly locked or unlocked.
+It keeps an intersection observer on all unlocked child items.
+Along with the buffer around the screen,
+this allows it to know when the state has changed such that we may need to lock or unlock different items.
+
+TODO(crbug.com/983050): Observe one item above and below the unlocked items too,
+without this, if the edge item is larger than the window,
+we can scroll empty space into the visible region.
+
+TODO(crbug.com/983046): Keep an intersection observer on the scroller.
+This allows us to know whether the scroller is offscreen.
+In that case we lock all elements
+and pause all activity.
+This includes if the scroller is contained in a locked element
+(e.g. nested in another virtual scroller).
+
+The virtual scroller keeps a mutation observer on itself
+so that it can react to elements being added, removed or moved around.
+When dealing with mutations,
+elements which are newly added are treated differently
+to elements which are removed and re-added.
+Newly added elements are immediately locked.
+This allows a large number of elements to be added,
+without a large rendering/style cost for these elements.
+
+The virtual scroller does not listen directly for scroll events
+and does not know or care whether it is in a scrollable region.
+It is tempting to try discover whether the scroller is contained in a scrolling region
+and then listen for scroll events,
+however the scroller may be contained in any number of nested scrollable regions
+and DOM changes can cause it to be reparented.
+Also, we only need to change state when an item enters or leaves the visible range
+but scroll events may occur much more frequently than that.
+
+The virtual scroller takes no action directly in response to these events.
+It simply ensures that a `requestAnimationFrame` (RAF) callback will run this frame
+(max one per frame).
+This callback is the "sync" callback.
+It will attempt to react to the new state of the world
+and try to ensure that the scroller is in sync with it.
+This is where we determine which elements to lock or unlock.
+
+When determining which items should be locked and which should be unlocked,
+the virtual scroller uses `getBoundingClientRect`
+to get the coordinates of its items,
+relative to the root viewport.
+It binary searches on the array of items
+to find the element at the top and bottom of the visible range.
+At the end of the sync,
+these and the elements in between them will be unlocked
+and all other elements will be locked.
+The scroller knows which elements are currently unlocked
+and does the minimal amount of locking and unlocking
+to bring it to the desired state.
+Also the intersection observers will be updated to match this range of elements.
+
+It is very possible that the range of elements we have unlocked
+is too big or too small for the viewport.
+We cannot know the rendered size of these elements
+until we have unlocked and measured them.
+In order to avoid extra forced layouts,
+we simply queue another sync callback for the next frame.
+We continue to queue sync callbacks until one of them makes no changes.
+
+Internally, the virtual scroller slots all children into a single slot.
+It changes the locked state of the light tree children directly.
+
+## Known issues specific to the current prototype
+
+### Display locking items directly
+
+The current prototype changes the locked state of the light tree children directly.
+This means that the scroller's actions can be detected from outside.
+It also means that an author cannot (in general) safely use display locking
+on the children of a virtual scroller.
+
+Other approaches do not have this issue,
+because they slot the items into more than one slot,
+however, this requires either manipulating the `slot` attribute on the items
+or [imperative slotting](https://www.chromestatus.com/feature/5711021289242624).
+
+### Binary searching the items
+
+The first problem with this is that it requires forced layout (see below).
+
+The second (potential) problem is that
+while JS presents an `Array` interface for the children of the virtual scroller,
+the reality is that in Blink,
+the elements are stored in a linked list
+with some extra logic to remember the most recent indexed access
+and use that to speed up subsequent index accesses
+(e.g. accessing `[n+1]` after `[n]` is fast).
+This makes the binary search actually O(number of children)
+because the C++ code must traverse a linked list.
+However C++ traversing a link list is very fast
+so this tends not to be noticeable.
+
+### Locked elements still have a cost
+
+While the descendants of locked elements are skipped for style and layout,
+the locked elements themselves are still traversed
+and participate in style and layout.
+In the scroller,
+the elements are locked with a size
+and behave just as an empty div with that size.
+This means that when we add many children to the virtual scroller,
+even though most of them are locked,
+there can still be quite a large style and rendering cost
+from the locked elements in aggregate.
+
+## Known issues common to many approaches
+
+### Intersection observers are slow
+
+Intersection observers signal the intersection state *after* it has happened.
+This means that by only reacting to intersection observers,
+the scroller may react late to scrolls and jumps.
+Once a scroll begins,
+it's likely that the element will keep up,
+since it is not using the details of the events to compute the state of the scroller.
+
+### Forced layouts to measure item sizes
+
+After unlocking, the scroller needs to know the rendered size of an element.
+In order to do that it must call `getBoundingClientRect`.
+This forces the browser to have clean style and layout
+for all unlocked elements in the document
+(whether this is expensive depends on what has changed since the last time layout).
+It may be better to perform these measurements in a
+[post animation frame callback](https://github.com/WICG/requestPostAnimationFrame/blob/master/explainer.md)
+when that feature becomes available
+because this callback guarantees that style and layout are clean,
+so measuring elements should be inexpensive.
+
+## Alternative approaches
+
+### Unlocked tree of divs with `<slot>`s for leaves (rejected)
+
+We could avoid the O(number of children) run of locked divs
+by building a tree of divs (e.g. a binary tree)
+and locking all of the slots except those containing the visible items.
+
+*PROBLEM:* This breaks margin collapsing between items
+and maybe other layout or style features.
+In order to make margin collapsing work correctly
+we would need to make all of the divs in this tree have style `display: contents`
+but for layout, this would have exactly the same performance problem as placing them all as siblings in one slot.
+
+### One visible slot in the middle (rejected)
+
+We could assign all of the visible items to a single slot,
+ensuring they behave correctly with respect to margin collapsing
+and keep all other items in other slots.
+
+We need to ensure that elements are slotted in their light-tree order
+for find-in-page, accessibility etc to work correctly.
+The simplest form of this is a three-slot approach
+with one slot for the invisible items at the top,
+another slot for the visible items in the middle
+and a third slot for the invisible items at the bottom.
+The top and bottom slot remain locked always
+and items are moved into the visible slot when they should be visible.
+The top and bottom slots are inside a locked div.
+These divs are locked with a size estimated to be the correct aggregate size for their slotted elements.
+
+*PROBLEM:* Gradually scrolling down moves items one at a time
+from the bottom slot, to the visible slot and then into the top slot
+but long-range jumps require moving O(number of children) items between slots.
+E.g. if the top items are visible and we jump to make the bottom items visible,
+then we have to assign almost all of the items that were in the bottom slot to the top slot.
+
+### Roaming visible slot (not preferred)
+
+This is similar to [One visible slot in the middle](#One-visible-slot-in-the-middle) approach
+but rather than a top and bottom slot,
+item assignment is divided over many slots.
+Each item has a natural "leaf" slot that it should be assigned to.
+All of the leaf slots are kept locked.
+There is a single visible slot that contains the currently unlocked items
+and it roams around between the leaf slots
+to ensure that order is correct for find-in-page etc.
+If we keep the number of items per slot low,
+then long jumps never cause a large number of items to be reassigned,
+at worst we need to reassign the currently visible items back to their leaf slots,
+move the visible slot to a new place
+and fill it with newly visible items.
+
+It's possible that there will be so many slots
+that once again we run into the problem of large numbers of empty divs.
+So we may need to maintain a tree of divs and `<slot>`s.
+Most of this tree would be locked
+but the path from the visible slot to the root would be unlocked.
+
+It looks like this:
+
+![Diagram of a sample roaming visible slot tree](roaming-slot.png)
+
+Original diagram [here](https://docs.google.com/drawings/d/1oZ8U16GzkxO3GaYLDygPsrmXiHO7SLNFXvVUK6WkG4I/edit)
+
+*CHALLENGES:* This approach does not seem to have any insurmountable problems,
+however it is not simple:
+- We need to ensure that the tree remains balanced in the face of mutations of the virtual scrollers contents.
+- A tree may introduce a large number of tree-only elements.
+ With a binary tree, this would be equal to the number of items in the scroller.
+ It might be worth using a larger branching factor, to reduce this cost.
+ E.g. in a 10-way tree the overhead is only 1/9 the number of leaves.
+- There is a lot of re-slotting of items.
+- The visible slot may contain a large number of elements (if elements are small)
+ and Blink has some [optimizations](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/html_slot_element.cc?q=symbol:HTMLSlotElement::NotifySlottedNodesOfFlatTreeChange)
+ that only work when slots contain <= 16 elements.
+- Adding slots and/or assigning elements to slots currently involves operations that are O(number of children).
+ Adding N slots can take O(N^2) time.
+ This was previously not a concern in Blink
+ because, in general, the style and layout costs dominated.
+ However display locking eliminates these costs,
+ leaving the slotting costs as the bottleneck when there are large numbers of items.
+
+### One slot per item (most promising alternative)
+
+This is similar to [Roaming visible slot](#Roaming-visible-slot).
+We have a tree of divs with slots as leaves
+but in this approach we have exactly one slot per item.
+For any item that should be unlocked,
+we ensure that all of its tree ancestors are unlocked
+and have style `display: contents`.
+All other nodes in the tree have style `display: block; contain: style layout`,
+to allow them to be locked.
+
+This has the effect of making all of the visible items siblings,
+from the perspective of layout,
+so that margin collapsing, etc. works correctly.
+It also ensures that not only are the invisible items and tree divs locked
+but they are *inside* locked ancestors,
+so do not incur *any* costs.
+
+There is no need to maintain spacer divs above and below the visible region.
+Instead, when we lock any tree element,
+we set its locked size to be its current visible size.
+If its contents don't change then this element has the correct aggregate size for its contents.
+If this element's parent is unlocked then this correct size will be used in sizing the parent.
+
+Mutations to the tree require size updates to propagate up the ancestor chain.
+E.g. inserting an element causes all of the elements ancestors to grow by our best guess at its size.
+So, the initial state of the tree
+(which comes from an initial insert)
+is that everything is an estimate or sum of estimates,
+with the sizes getting more accurate
+as more elements are rendered, measured and re-locked with correct sizes.
+
+It's likely that the sizes above will be off by some amount due to margins
+but they should be good enough for maintaining a usable scrollbar.
+
+*CHALLENGES:* This approach does not seem to have any insurmountable problems,
+however it is not so simple.
+It has a subset of the challenges of [Roaming visible slot](#Roaming-visible-slot):
+
+- Needs a balanced tree.
+- Possible large number of tree-only elements.
+- Slot performance issues.
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/docs/roaming-slot.png b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/docs/roaming-slot.png
new file mode 100644
index 00000000000..2f9b6844694
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/docs/roaming-slot.png
Binary files differ
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/find-element.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/find-element.mjs
new file mode 100644
index 00000000000..c25edc0a7fd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/find-element.mjs
@@ -0,0 +1,104 @@
+/**
+ * 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.
+ *
+ * @fileoverview Utilities for binary searching by layed-out pixed offset in a
+ * list of elements.
+ * @package
+ */
+
+/** Symbols for use with @see findElement */
+export const BIAS_LOW = Symbol('BIAS_LOW');
+export const BIAS_HIGH = Symbol('BIAS_HIGH');
+
+function getBound(elements, edgeIndex) {
+ const element = elements[Math.floor(edgeIndex / 2)];
+ const rect = element.getBoundingClientRect();
+ return edgeIndex % 2 ? rect.bottom : rect.top;
+}
+
+/**
+ * Does the actual work of binary searching. This searches amongst the 2*N edges
+ * of the N elements. Returns the index of an edge found, 2i is the low edge of
+ * the ith element, 2i+1 is the high edge of the ith element. If |bias| is low
+ * then we find the index of the lowest edge >= offset. Otherwise we find index
+ * of the highest edge > offset.
+ */
+function findEdgeIndex(elements, offset, bias) {
+ let low = 0;
+ let high = elements.length * 2 - 1;
+ while (low < high) {
+ const i = Math.floor((low + high) / 2);
+ const bound = getBound(elements, i);
+ if (bias === BIAS_LOW) {
+ if (bound < offset) {
+ low = i + 1;
+ } else {
+ high = i;
+ }
+ } else {
+ if (offset < bound) {
+ high = i;
+ } else {
+ low = i + 1;
+ }
+ }
+ }
+ return low;
+}
+
+/**
+ * Binary searches inside the array |elements| to find an element containing or
+ * nearest to |offset| (based on @see Element#getBoundingClientRect()). Assumes
+ * that the elements are already sorted in increasing pixel order. |bias|
+ * controls what happens if |offset| is not contained within any element or if
+ * |offset| is contained with 2 elements (this only happens if there is no
+ * margin between the elements). If |bias| is BIAS_LOW, then this selects the
+ * lower element nearest |offset|, otherwise it selects the higher element.
+ *
+ * Returns null if |offset| is not within any element.
+ *
+ * @param {!Element[]} elements An array of Elements in display order,
+ * i.e. the pixel offsets of later element are higher than those of earlier
+ * elements.
+ * @param {!number} offset The target offset in pixels to search for.
+ * @param {!Symbol} bias Controls whether we prefer a higher or lower element
+ * when there is a choice between two elements.
+ */
+export function findElement(elements, offset, bias) {
+ if (elements.length === 0) {
+ return null;
+ }
+ // Check if the offset is outside the range entirely.
+ if (offset < getBound(elements, 0) ||
+ offset > getBound(elements, elements.length * 2 - 1)) {
+ return null;
+ }
+
+ let edgeIndex = findEdgeIndex(elements, offset, bias);
+
+ // Fix up edge cases.
+ if (bias === BIAS_LOW) {
+ // bound(0)..bound(edgeIndex) < offset <= bound(edgeIndex+1) ...
+ // If we bias low and we got a low edge and we weren't exactly on the edge
+ // then we want to select the element that's lower.
+ if (edgeIndex % 2 === 0) {
+ const bound = getBound(elements, edgeIndex);
+ if (offset < bound) {
+ edgeIndex--;
+ }
+ }
+ } else {
+ // bound(0)..bound(edgeIndex - 1) <= offset < bound(edgeIndex) ...
+ // If we bias high and we got a low edge, we need to check if we were
+ // exactly on the edge of the previous element.
+ if (edgeIndex % 2 === 0) {
+ const bound = getBound(elements, edgeIndex - 1);
+ if (offset === bound) {
+ edgeIndex--;
+ }
+ }
+ }
+ return elements[Math.floor(edgeIndex / 2)];
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/index.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/index.mjs
new file mode 100644
index 00000000000..daef60f7232
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/index.mjs
@@ -0,0 +1,57 @@
+/**
+ * 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.
+ *
+ * @fileoverview This file defines virtual-scroller element.
+ * EXPLAINER: https://github.com/fergald/virtual-scroller/blob/master/README.md
+ * TEST PATH: third_party/blink/web_tests/http/tests/virtual-scroller/*
+ * third_party/blink/web_tests/wpt_internal/virtual-scroller/*
+ * @package
+ */
+import {VisibilityManager} from './visibility-manager.mjs';
+
+function styleSheetFactory() {
+ let styleSheet;
+ return () => {
+ if (!styleSheet) {
+ styleSheet = new CSSStyleSheet();
+ styleSheet.replaceSync(`
+:host {
+ display: block;
+}
+
+::slotted(*) {
+ display: block !important;
+ contain: layout style;
+}
+`);
+ }
+ return styleSheet;
+ };
+}
+
+/**
+ * The class backing the virtual-scroller custom element.
+ */
+export class VirtualScrollerElement extends HTMLElement {
+ constructor() {
+ super();
+
+ const shadowRoot = this.attachShadow({mode: 'closed'});
+ shadowRoot.adoptedStyleSheets = [styleSheetFactory()()];
+ shadowRoot.appendChild(document.createElement('slot'));
+
+ const visibilityManager = new VisibilityManager(this.children);
+
+ new ResizeObserver(() => {
+ visibilityManager.scheduleSync();
+ }).observe(this);
+
+ new MutationObserver(records => {
+ visibilityManager.applyMutationObserverRecords(records);
+ }).observe(this, {childList: true});
+ }
+}
+
+customElements.define('virtual-scroller', VirtualScrollerElement);
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/sets.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/sets.mjs
new file mode 100644
index 00000000000..9b1aff8eca1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/sets.mjs
@@ -0,0 +1,24 @@
+/**
+ * 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.
+ *
+ * @fileoverview Utility functions for set operations.
+ * @package
+ */
+
+/*
+ * Returns the set of elements in |a| that are not in |b|.
+ *
+ * @param {!Set} a A set of elements.
+ * @param {!Set} b A set of elements.
+*/
+export function difference(a, b) {
+ const result = new Set();
+ for (const element of a) {
+ if (!b.has(element)) {
+ result.add(element);
+ }
+ }
+ return result;
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs
new file mode 100644
index 00000000000..ecc160f9f0d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs
@@ -0,0 +1,407 @@
+/**
+ * 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.
+ *
+ * @fileoverview This file provides the class backing the virtual-scroller
+ * element.
+ * @package
+ */
+import * as sets from './sets.mjs';
+import * as findElement from './find-element.mjs';
+
+
+// This controls how much above and below the current screen we
+// reveal, e.g. 1 = 1 screen of content.
+const BUFFER = 0.2;
+// When we know about the heights of elements we default this height.
+const DEFAULT_HEIGHT_ESTIMATE_PX = 100;
+// When we lock an element, we use this as the width. We use 1px because locked
+// items will not resize when their container changes and so could result in a
+// horizontal scroll-bar appearing if it they are wide enough.
+const LOCKED_WIDTH_PX = 1;
+
+/**
+ * Represents a range of elements from |low| to |high|, inclusive.
+ * If either |low| or |high| are null then we treat this as an empty range.
+ */
+class ElementBounds {
+ /** @const {Element} */
+ low;
+ /** @const {Element} */
+ high;
+
+ constructor(low, high) {
+ this.low = low;
+ this.high = high;
+ }
+
+ // Returns a Set containing all of the elements from low to high.
+ elementSet() {
+ const result = new Set();
+ if (this.low === null || this.high === null) {
+ return result;
+ }
+ let element = this.low;
+ while (element) {
+ result.add(element);
+ if (element === this.high) {
+ break;
+ }
+ element = element.nextElementSibling;
+ }
+ return result;
+ }
+}
+
+const EMPTY_ELEMENT_BOUNDS = new ElementBounds(null, null);
+
+/**
+ * Manages measuring and estimating sizes of elements.
+ *
+ * This tracks an average measured element size as elements are added
+ * and removed.
+*/
+class SizeManager {
+ #sizes = new WeakMap();
+
+ #totalMeasuredSize = 0;
+ #measuredCount = 0;
+
+ /**
+ * Measures and stores |element|'s size. If |element| was measured
+ * previously, this updates everything to use the new current size.
+ *
+ * @param {!Element} element The element to measure.
+ */
+ measure(element) {
+ let oldSize = this.#sizes.get(element);
+ if (oldSize === undefined) {
+ oldSize = 0;
+ this.#measuredCount++;
+ }
+ const newSize = element.getBoundingClientRect().height;
+ this.#totalMeasuredSize += newSize - oldSize;
+ this.#sizes.set(element, newSize);
+ }
+
+ /**
+ * Returns a size for |element|, either the last stored size or an
+ * estimate based on all other previously measured elements or a
+ * default.
+ *
+ * @param {!Element} element The element to produce a size for.
+ */
+ getHopefulSize(element) {
+ const size = this.#sizes.get(element);
+ return size === undefined ? this.#getAverageSize() : size;
+ }
+
+ #getAverageSize = () => {
+ return this.#measuredCount > 0 ?
+ this.#totalMeasuredSize / this.#measuredCount :
+ DEFAULT_HEIGHT_ESTIMATE_PX;
+ }
+
+ /**
+ * Removes all data related to |element| from the manager.
+ *
+ * @param {!Element} element The element to remove.
+ */
+ remove(element) {
+ const oldSize = this.#sizes.get(element);
+ if (oldSize === undefined) {
+ return;
+ }
+ this.#totalMeasuredSize -= oldSize;
+ this.#measuredCount--;
+ this.#sizes.delete(element);
+ }
+}
+
+/**
+ * Manages the visibility (locked/unlocked state) of a list of
+ * elements. This list of elements is assumed to be in vertical
+ * display order (e.g. from lowest to highest offset).
+ *
+ * It uses resize and intersection observers on all of the visible
+ * elements to ensure that changes that impact visibility cause us to
+ * recalulate things (e.g. scrolling, restyling).
+*/
+export class VisibilityManager {
+ #sizeManager = new SizeManager();
+ #elements;
+ #syncRAFToken;
+
+ #elementIntersectionObserver;
+ #elementResizeObserver;
+
+ #revealed = new Set();
+
+ constructor(elements) {
+ this.#elements = elements;
+
+ // We want to sync if any element's size changes or if it becomes
+ // more/less visible.
+ this.#elementIntersectionObserver = new IntersectionObserver(() => {
+ this.scheduleSync();
+ });
+ // TODO(fergal): Remove this? I'm not sure that we need the resize
+ // observer. Any resize that is important to us seems like it will
+ // also involve an intersection change.
+ this.#elementResizeObserver = new ResizeObserver(() => {
+ this.scheduleSync();
+ });
+
+ for (const element of this.#elements) {
+ this.#didAdd(element);
+ }
+ this.scheduleSync();
+ }
+
+ /**
+ * Attempts to unlock a range of elements suitable for the current
+ * viewport. This causes one forced layout.
+ */
+ #sync = () => {
+ if (this.#elements.length === 0) {
+ return;
+ }
+
+ // The basic idea is ...
+ // The forced layout occurs at the start. We then use the laid out
+ // coordinates (which are based on a mix of real sizes for
+ // unlocked elements and the estimated sizes at the time of
+ // locking for locked elements) to calculate a set of elements
+ // which should be revealed. We use unlock/lock to move to this
+ // new set of revealed elements. We will check in the next frame
+ // whether we got it correct.
+
+ // This causes a forced layout and takes measurements of all
+ // currently revealed elements.
+ this.#measureRevealed();
+
+ // Compute the pixel bounds of what we would like to reveal. Then
+ // find the elements corresponding to these bounds.
+ // TODO(fergal): Use nearest scrolling ancestor?
+ const desiredLow = 0 - window.innerHeight * BUFFER;
+ const desiredHigh = window.innerHeight + window.innerHeight * BUFFER;
+ const newBounds = this.#findElementBounds(desiredLow, desiredHigh);
+ const newRevealed = newBounds.elementSet();
+
+ // TODO(fergal): We need to observe 1 element off the end of the
+ // list, to cope with e.g. the scrolling region suddenly growing.
+
+ // Lock and unlock the minimal set of elements to get us to the
+ // new state.
+ const toHide = sets.difference(this.#revealed, newRevealed);
+ toHide.forEach(e => this.#hide(e));
+ const toReveal = sets.difference(newRevealed, this.#revealed);
+ toReveal.forEach(e => this.#reveal(e));
+
+ // Now we have revealed what we hope will fill the screen. It
+ // could be incorrect. Rather than measuring now and correcting it
+ // which would involve an unknown number of forced layouts, we
+ // come back next frame and try to make it better. We know we can
+ // stop when we didn't hide or reveal any elements.
+ if (toHide.size > 0 || toReveal.size > 0) {
+ this.scheduleSync();
+ }
+ }
+
+ /**
+ * Searches within the managed elements and returns an ElementBounds
+ * object. This object may represent an empty range or a range whose low
+ * element contains or is lower than |low| (or the lowest element
+ * possible). Similarly for |high|.
+ *
+ * @param {!number} low The lower bound to locate.
+ * @param {!number} high The upper bound to locate.
+ */
+ #findElementBounds = (low, high) => {
+ const lowElement = findElement.findElement(
+ this.#elements, low, findElement.BIAS_LOW);
+ const highElement = findElement.findElement(
+ this.#elements, high, findElement.BIAS_HIGH);
+
+ if (lowElement === null) {
+ if (highElement === null) {
+ return EMPTY_ELEMENT_BOUNDS;
+ } else {
+ return new ElementBounds(this.#elements[0], highElement);
+ }
+ } else if (highElement === null) {
+ return new ElementBounds(
+ lowElement, this.#elements[this.#elements.length - 1]);
+ }
+ return new ElementBounds(lowElement, highElement);
+ }
+
+ /**
+ * Updates the size manager with all of the currently revealed
+ * elements' sizes. This will cause a forced layout.
+ */
+ #measureRevealed = () => {
+ for (const element of this.#revealed) {
+ this.#sizeManager.measure(element);
+ }
+ }
+
+ /**
+ * Reveals |element| so that it can be rendered. This includes
+ * unlocking and adding to various observers.
+ *
+ * @param {!Element} element The element to reveal.
+ */
+ #reveal = element => {
+ this.#revealed.add(element);
+ this.#elementIntersectionObserver.observe(element);
+ this.#elementResizeObserver.observe(element);
+ this.#unlock(element);
+ }
+
+ #logLockingError = (operation, reason, element) => {
+ // TODO: Figure out the LAPIs error/warning logging story.
+ console.error('Rejected: ', operation, element, reason); // eslint-disable-line no-console
+ }
+
+ /**
+ * Unlocks |element|.
+ *
+ * @param {!Element} element The element to unlock.
+ */
+ #unlock = element => {
+ element.displayLock.commit().catch(reason => {
+ // Only warn if the unlocked failed and we should be revealed.
+ if (this.#revealed.has(element)) {
+ this.#logLockingError('Commit', reason, element);
+ }
+ });
+ }
+
+ /**
+ * Hides |element| so that it cannot be rendered. This includes
+ * locking and removing from various observers.
+ *
+ * @param {!Element} element The element to hide.
+ */
+ #hide = element => {
+ this.#revealed.delete(element);
+ this.#elementIntersectionObserver.unobserve(element);
+ this.#elementResizeObserver.unobserve(element);
+ element.displayLock.acquire({
+ timeout: Infinity,
+ activatable: true,
+ size: [LOCKED_WIDTH_PX, this.#sizeManager.getHopefulSize(element)],
+ }).catch(reason => {
+ // Only warn if the lock failed and we should be locked.
+ if (!this.#revealed.has(element)) {
+ this.#logLockingError('Acquire', reason, element);
+ }
+ });
+ }
+
+ /**
+ * Notify the manager that |element| has been added to the list of
+ * managed elements.
+ *
+ * @param {!Element} element The element that was added.
+ */
+ #didAdd = element => {
+ // Added children should be invisible initially. We want to make them
+ // invisible at this MutationObserver timing, so that there is no
+ // frame where the browser is asked to render all of the children
+ // (which could be a lot).
+ this.#hide(element);
+ }
+
+ /**
+ * Notify the manager that |element| has been removed from the list
+ * of managed elements.
+ *
+ * @param {!Element} element The element that was removed.
+ */
+ #didRemove = element => {
+ // Removed children should be made visible again. We should stop
+ // observing them and discard any size info we have for them as it
+ // may have become incorrect.
+ //
+ // TODO(fergal): Decide whether to also unlock if
+ // displayLock.locked is true. That would only be necessary if we
+ // got out of sync between this.#revealed and the locked state. So
+ // for now, assume are not buggy.
+ if (this.#revealed.has(element)) {
+ this.#unlock(element);
+ }
+ this.#revealed.delete(element);
+ this.#elementIntersectionObserver.unobserve(element);
+ this.#elementResizeObserver.unobserve(element);
+ this.#sizeManager.remove(element);
+ }
+
+ /**
+ * Ensures that @see #sync() will be called at the next animation frame.
+ */
+ scheduleSync() {
+ if (this.#syncRAFToken !== undefined) {
+ return;
+ }
+
+ this.#syncRAFToken = window.requestAnimationFrame(() => {
+ this.#syncRAFToken = undefined;
+ this.#sync();
+ });
+ }
+
+ /**
+ * Applys |records| generated by a mutation event to the manager.
+ * This computes the elements that were newly added/removed and
+ * notifies the managers for each.
+ *
+ * @param {!Object} records The mutations records.
+ */
+ applyMutationObserverRecords(records) {
+ // It's unclear if we can support children which are not
+ // elements. We cannot control their visibility using display
+ // locking but we can just leave them alone.
+ //
+ // Relevant mutations are any additions or removals, including
+ // non-elements and also elements that are removed and then
+ // re-added as this may impact element bounds.
+ let relevantMutation = false;
+ const toRemove = new Set();
+ for (const record of records) {
+ relevantMutation = relevantMutation || record.removedNodes.length > 0;
+ for (const node of record.removedNodes) {
+ if (node.nodeType === Node.ELEMENT_NODE) {
+ toRemove.add(node);
+ }
+ }
+ }
+
+ const toAdd = new Set();
+ for (const record of records) {
+ relevantMutation = relevantMutation || record.addedNodes.length > 0;
+ for (const node of record.addedNodes) {
+ if (node.nodeType === Node.ELEMENT_NODE) {
+ if (toRemove.has(node)) {
+ toRemove.delete(node);
+ } else {
+ toAdd.add(node);
+ }
+ }
+ }
+ }
+ for (const node of toRemove) {
+ this.#didRemove(node);
+ }
+ for (const node of toAdd) {
+ this.#didAdd(node);
+ }
+
+ if (relevantMutation) {
+ this.scheduleSync();
+ }
+ }
+}
+
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/async_iterator.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/async_iterator.mjs
index 0da4854b99d..a83dba41c20 100644
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/async_iterator.mjs
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/async_iterator.mjs
@@ -16,6 +16,8 @@ const AsyncIteratorPrototype = Object.getPrototypeOf(
const StorageAreaAsyncIteratorPrototype = {
__proto__: AsyncIteratorPrototype,
+ [Symbol.toStringTag]: 'StorageArea AsyncIterator',
+
next() {
const performDatabaseOperation = _performDatabaseOperation.get(this);
if (!performDatabaseOperation) {
@@ -42,6 +44,12 @@ const StorageAreaAsyncIteratorPrototype = {
},
};
+Object.defineProperty(
+ StorageAreaAsyncIteratorPrototype,
+ Symbol.toStringTag,
+ {writable: false, enumerable: false}
+);
+
function getNextIterResult(iter, performDatabaseOperation) {
return performDatabaseOperation(async (transaction, store) => {
const lastKey = _lastKey.get(iter);
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs
index b5272ea5d7b..88ef25e818a 100644
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs
@@ -5,16 +5,18 @@
import {createStorageAreaAsyncIterator} from './async_iterator.mjs';
import {promiseForRequest, promiseForTransaction, throwForDisallowedKey} from './idb_utils.mjs';
-// TODOs/spec-noncompliances:
+// Overall TODOs/spec-noncompliances:
// - Susceptible to tampering of built-in prototypes and globals. We want to
// work on tooling to ameliorate that.
const DEFAULT_STORAGE_AREA_NAME = 'default';
const DEFAULT_IDB_STORE_NAME = 'store';
+// TODO(crbug.com/977470): this should be handled via infrastructure that
+// avoids putting it in the module map entirely, not as a runtime check.
+// Several web platform tests fail because of this.
if (!self.isSecureContext) {
- throw new DOMException(
- 'KV Storage is only available in secure contexts', 'SecurityError');
+ throw new TypeError('KV Storage is only available in secure contexts');
}
export class StorageArea {
@@ -132,8 +134,25 @@ export class StorageArea {
}
StorageArea.prototype[Symbol.asyncIterator] = StorageArea.prototype.entries;
-
-export const storage = new StorageArea(DEFAULT_STORAGE_AREA_NAME);
+StorageArea.prototype[Symbol.toStringTag] = 'StorageArea';
+
+// Override the defaults that are implied by using class declarations and
+// assignment, to be more Web IDL-ey.
+// https://github.com/heycam/webidl/issues/738 may modify these a bit.
+Object.defineProperties(StorageArea.prototype, {
+ set: {enumerable: true},
+ get: {enumerable: true},
+ delete: {enumerable: true},
+ clear: {enumerable: true},
+ keys: {enumerable: true},
+ values: {enumerable: true},
+ entries: {enumerable: true},
+ backingStore: {enumerable: true},
+ [Symbol.asyncIterator]: {enumerable: false},
+ [Symbol.toStringTag]: {writable: false, enumerable: false}
+});
+
+export default new StorageArea(DEFAULT_STORAGE_AREA_NAME);
async function performDatabaseOperation(
promise, setPromise, name, mode, steps) {
@@ -145,7 +164,9 @@ async function performDatabaseOperation(
const transaction = database.transaction(DEFAULT_IDB_STORE_NAME, mode);
const store = transaction.objectStore(DEFAULT_IDB_STORE_NAME);
- return steps(transaction, store);
+ const result = steps(transaction, store);
+ transaction.commit();
+ return result;
}
function initializeDatabasePromise(setPromise, databaseName) {
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp b/chromium/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp
index 2a7e3b38f14..255d05543d1 100644
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp
@@ -7,14 +7,17 @@
third_party/blink/public/blink_resources.grd.
-->
<include name="IDR_LAYERED_API_BLANK_INDEX_MJS" file="../renderer/core/script/resources/layered_api/blank/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_INTERNAL_REFLECTION_MJS" file="../renderer/core/script/resources/layered_api/elements/internal/reflection.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_SWITCH_FACE_UTILS_MJS" file="../renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_SWITCH_INDEX_MJS" file="../renderer/core/script/resources/layered_api/elements/switch/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_SWITCH_STYLE_MJS" file="../renderer/core/script/resources/layered_api/elements/switch/style.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_SWITCH_TRACK_MJS" file="../renderer/core/script/resources/layered_api/elements/switch/track.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_TOAST_INDEX_MJS" file="../renderer/core/script/resources/layered_api/elements/toast/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_VIRTUAL_SCROLLER_FIND_ELEMENT_MJS" file="../renderer/core/script/resources/layered_api/elements/virtual-scroller/find-element.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_VIRTUAL_SCROLLER_INDEX_MJS" file="../renderer/core/script/resources/layered_api/elements/virtual-scroller/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_VIRTUAL_SCROLLER_SETS_MJS" file="../renderer/core/script/resources/layered_api/elements/virtual-scroller/sets.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
+ <include name="IDR_LAYERED_API_ELEMENTS_VIRTUAL_SCROLLER_VISIBILITY_MANAGER_MJS" file="../renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
<include name="IDR_LAYERED_API_KV_STORAGE_ASYNC_ITERATOR_MJS" file="../renderer/core/script/resources/layered_api/kv-storage/async_iterator.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
<include name="IDR_LAYERED_API_KV_STORAGE_IDB_UTILS_MJS" file="../renderer/core/script/resources/layered_api/kv-storage/idb_utils.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
<include name="IDR_LAYERED_API_KV_STORAGE_INDEX_MJS" file="../renderer/core/script/resources/layered_api/kv-storage/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
- <include name="IDR_LAYERED_API_VIRTUAL_SCROLLER_INDEX_MJS" file="../renderer/core/script/resources/layered_api/virtual-scroller/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
- <include name="IDR_LAYERED_API_VIRTUAL_SCROLLER_ITEM_SOURCE_MJS" file="../renderer/core/script/resources/layered_api/virtual-scroller/item-source.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
- <include name="IDR_LAYERED_API_VIRTUAL_SCROLLER_VIRTUAL_REPEATER_MJS" file="../renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
- <include name="IDR_LAYERED_API_VIRTUAL_SCROLLER_VIRTUAL_SCROLLER_MJS" file="../renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
- <include name="IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_BASE_MJS" file="../renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
- <include name="IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_GRID_MJS" file="../renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
- <include name="IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_MJS" file="../renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
</grit-part>
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/README.chromium b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/README.chromium
deleted file mode 100644
index e8b4d5d0007..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/README.chromium
+++ /dev/null
@@ -1,12 +0,0 @@
-Name: virtual-scroller Layered API
-URL: https://github.com/valdrinkoshi/virtual-scroller
-Version: 58659cee10c5d9237821d5c475dac89720bd995d
-Security Critical: no
-
-Description:
-Temporarily, the files under this directory are authored by Chromium Authors
-on a github repository, and then imported to Chromium repository directly here,
-until a long-term Layered API development plan is settled.
-
-Local Modifications:
-None (except for renaming virtual-scroller-element.mjs to index.mjs)
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/index.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/index.mjs
deleted file mode 100644
index 8cdad8091f7..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/index.mjs
+++ /dev/null
@@ -1,213 +0,0 @@
-import {_item, _key, ItemSource} from './item-source.mjs';
-import {default as Layout1dGrid} from './layouts/layout-1d-grid.mjs';
-import {default as Layout1d} from './layouts/layout-1d.mjs';
-import {VirtualScroller} from './virtual-scroller.mjs';
-
-export {ItemSource};
-
-/** Properties */
-const _scroller = Symbol();
-const _createElement = Symbol();
-const _updateElement = Symbol();
-const _recycleElement = Symbol();
-const _nodePool = Symbol();
-const _rawItemSource = Symbol();
-const _itemSource = Symbol();
-const _elementSource = Symbol();
-const _firstConnected = Symbol();
-/** Functions */
-const _render = Symbol();
-
-export class VirtualScrollerElement extends HTMLElement {
- constructor() {
- super();
- this[_scroller] = null;
- // Default create/update/recycleElement.
- this[_nodePool] = [];
- let childTemplate = null;
- this[_createElement] = () => {
- if (this[_nodePool] && this[_nodePool].length) {
- return this[_nodePool].pop();
- }
- if (!childTemplate) {
- const template = this.querySelector('template');
- childTemplate = template && template.content.firstElementChild ?
- template.content.firstElementChild :
- document.createElement('div');
- }
- return childTemplate.cloneNode(true);
- };
- this[_updateElement] = (element, item) => element.textContent =
- item.toString();
- this[_recycleElement] = (element) => this[_nodePool].push(element);
-
- this[_itemSource] = this[_rawItemSource] = null;
- this[_elementSource] = {};
-
- this[_firstConnected] = false;
- }
-
- connectedCallback() {
- if (!this[_firstConnected]) {
- this.attachShadow({mode: 'open'}).innerHTML = `
-<style>
- :host {
- display: block;
- position: relative;
- contain: strict;
- height: 150px;
- overflow: auto;
- }
- :host([hidden]) {
- display: none;
- }
- ::slotted(*) {
- box-sizing: border-box;
- }
- :host([layout=vertical]) ::slotted(*) {
- width: 100%;
- }
- :host([layout=horizontal]) ::slotted(*) {
- height: 100%;
- }
-</style>
-<slot></slot>`;
- // Set default values.
- if (!this.layout) {
- this.layout = 'vertical';
- }
- // Enables rendering.
- this[_firstConnected] = true;
- }
- this[_render]();
- }
-
- static get observedAttributes() {
- return ['layout'];
- }
-
- attributeChangedCallback(name, oldVal, newVal) {
- this[_render]();
- }
-
- get layout() {
- return this.getAttribute('layout');
- }
- set layout(layout) {
- this.setAttribute('layout', layout);
- }
-
- get itemSource() {
- return this[_itemSource];
- }
- set itemSource(itemSource) {
- // No Change.
- if (this[_rawItemSource] === itemSource) {
- return;
- }
- this[_rawItemSource] = itemSource;
- this[_itemSource] = Array.isArray(itemSource) ?
- ItemSource.fromArray(itemSource) :
- itemSource;
- this[_render]();
- }
-
- get createElement() {
- return this[_createElement];
- }
- set createElement(fn) {
- // Resets default recycling.
- if (this[_nodePool]) {
- this.recycleElement = null;
- }
- this[_createElement] = fn;
- // Invalidate wrapped function.
- this[_elementSource].createElement = null;
- this[_render]();
- }
-
- get updateElement() {
- return this[_updateElement];
- }
- set updateElement(fn) {
- this[_updateElement] = fn;
- // Invalidate wrapped function.
- this[_elementSource].updateElement = null;
- this[_render]();
- }
-
- get recycleElement() {
- return this[_recycleElement];
- }
- set recycleElement(fn) {
- // Marks default recycling changed.
- this[_nodePool] = null;
- this[_recycleElement] = fn;
- // Invalidate wrapped function.
- this[_elementSource].recycleElement = null;
- this[_render]();
- }
-
- itemsChanged() {
- if (this[_scroller]) {
- // Render because length might have changed.
- this[_render]();
- // Request reset because items might have changed.
- this[_scroller].requestReset();
- }
- }
-
- scrollToIndex(index, { position = 'start' } = {}) {
- if (this[_scroller]) {
- this[_scroller].layout.scrollToIndex(index, position);
- }
- }
-
- [_render]() {
- // Wait first connected as scroller needs to measure
- // sizes of container and children.
- if (!this[_firstConnected] || !this.createElement) {
- return;
- }
- if (!this[_scroller]) {
- this[_scroller] =
- new VirtualScroller({container: this, scrollTarget: this});
- }
- const scroller = this[_scroller];
-
- const layoutAttr = this.layout;
- const Layout = layoutAttr.endsWith('-grid') ? Layout1dGrid : Layout1d;
- const direction =
- layoutAttr.startsWith('horizontal') ? 'horizontal' : 'vertical';
- const layout = scroller.layout instanceof Layout &&
- scroller.layout.direction === direction ?
- scroller.layout :
- new Layout({direction});
-
- let {createElement, updateElement, recycleElement} = this[_elementSource];
- if (!createElement) {
- createElement = this[_elementSource].createElement = (index) =>
- this.createElement(this.itemSource[_item](index), index);
- }
- if (this.updateElement && !updateElement) {
- updateElement = this[_elementSource].updateElement = (element, index) =>
- this.updateElement(element, this.itemSource[_item](index), index);
- }
- if (this.recycleElement && !recycleElement) {
- recycleElement = this[_elementSource].recycleElement = (element, index) =>
- this.recycleElement(element, this.itemSource[_item](index), index);
- }
-
- const elementKey = this.itemSource ? this.itemSource[_key] : null;
- const totalItems = this.itemSource ? this.itemSource.length : 0;
- Object.assign(scroller, {
- layout,
- createElement,
- updateElement,
- recycleElement,
- elementKey,
- totalItems
- });
- }
-}
-customElements.define('virtual-scroller', VirtualScrollerElement);
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/item-source.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/item-source.mjs
deleted file mode 100644
index 255e97b245c..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/item-source.mjs
+++ /dev/null
@@ -1,47 +0,0 @@
-export const _getLength = Symbol();
-export const _item = Symbol();
-export const _key = Symbol();
-
-export class ItemSource {
- constructor({getLength, item, key}) {
- if (typeof getLength !== 'function') {
- throw new TypeError('getLength option must be a function');
- }
- if (typeof item !== 'function') {
- throw new TypeError('item option must be a function');
- }
- if (typeof key !== 'function') {
- throw new TypeError('key option must be a function');
- }
-
- this[_getLength] = getLength;
- this[_item] = item;
- this[_key] = key;
- }
-
- static fromArray(array, key) {
- if (!Array.isArray(array)) {
- throw new TypeError('First argument to fromArray() must be an array');
- }
- if (typeof key !== 'function' && key !== undefined) {
- throw new TypeError(
- 'Second argument to fromArray() must be a function or undefined');
- }
-
- return new this({
- getLength() {
- return array.length;
- },
- item(index) {
- return array[index];
- },
- key(index) {
- return key ? key(array[index], index) : array[index];
- }
- });
- }
-
- get length() {
- return this[_getLength]();
- }
-}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.mjs
deleted file mode 100644
index 89a9a9e8106..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.mjs
+++ /dev/null
@@ -1,320 +0,0 @@
-export default class Layout extends EventTarget {
- constructor(config) {
- super();
-
- this._physicalMin = 0;
- this._physicalMax = 0;
-
- this._first = -1;
- this._last = -1;
-
- this._latestCoords = {left: 0, top: 0};
-
- this._itemSize = {width: 100, height: 100};
- this._spacing = 0;
-
- this._sizeDim = 'height';
- this._secondarySizeDim = 'width';
- this._positionDim = 'top';
- this._secondaryPositionDim = 'left';
- this._direction = 'vertical';
-
- this._scrollPosition = 0;
- this._scrollError = 0;
- this._viewportSize = {width: 0, height: 0};
- this._totalItems = 0;
-
- this._scrollSize = 1;
-
- this._overhang = 150;
-
- this._pendingReflow = false;
-
- this._scrollToIndex = -1;
- this._scrollToAnchor = 0;
-
- Object.assign(this, config);
- }
-
- // public properties
-
- get totalItems() {
- return this._totalItems;
- }
- set totalItems(num) {
- if (num !== this._totalItems) {
- this._totalItems = num;
- this._maxIdx = num - 1;
- this._scheduleReflow();
- }
- }
-
- get direction() {
- return this._direction;
- }
- set direction(dir) {
- // Force it to be either horizontal or vertical.
- dir = (dir === 'horizontal') ? dir : 'vertical';
- if (dir !== this._direction) {
- this._direction = dir;
- this._sizeDim = (dir === 'horizontal') ? 'width' : 'height';
- this._secondarySizeDim = (dir === 'horizontal') ? 'height' : 'width';
- this._positionDim = (dir === 'horizontal') ? 'left' : 'top';
- this._secondaryPositionDim = (dir === 'horizontal') ? 'top' : 'left';
- this._scheduleReflow();
- }
- }
-
- get itemSize() {
- return this._itemSize;
- }
- set itemSize(dims) {
- const {_itemDim1, _itemDim2} = this;
- Object.assign(this._itemSize, dims);
- if (_itemDim1 !== this._itemDim1 || _itemDim2 !== this._itemDim2) {
- if (_itemDim2 !== this._itemDim2) {
- this._itemDim2Changed();
- } else {
- this._scheduleReflow();
- }
- }
- }
-
- get spacing() {
- return this._spacing;
- }
- set spacing(px) {
- if (px !== this._spacing) {
- this._spacing = px;
- this._scheduleReflow();
- }
- }
-
- get viewportSize() {
- return this._viewportSize;
- }
- set viewportSize(dims) {
- const {_viewDim1, _viewDim2} = this;
- Object.assign(this._viewportSize, dims);
- if (_viewDim2 !== this._viewDim2) {
- this._viewDim2Changed();
- } else if (_viewDim1 !== this._viewDim1) {
- this._checkThresholds();
- }
- }
-
- get viewportScroll() {
- return this._latestCoords;
- }
- set viewportScroll(coords) {
- Object.assign(this._latestCoords, coords);
- const oldPos = this._scrollPosition;
- this._scrollPosition = this._latestCoords[this._positionDim];
- if (oldPos !== this._scrollPosition) {
- this._scrollPositionChanged(oldPos, this._scrollPosition);
- }
- this._checkThresholds();
- }
-
- // private properties
-
- get _delta() {
- return this._itemDim1 + this._spacing;
- }
-
- get _itemDim1() {
- return this._itemSize[this._sizeDim];
- }
-
- get _itemDim2() {
- return this._itemSize[this._secondarySizeDim];
- }
-
- get _viewDim1() {
- return this._viewportSize[this._sizeDim];
- }
-
- get _viewDim2() {
- return this._viewportSize[this._secondarySizeDim];
- }
-
- get _num() {
- if (this._first === -1 || this._last === -1) {
- return 0;
- }
- return this._last - this._first + 1;
- }
-
- // public methods
-
- reflowIfNeeded() {
- if (this._pendingReflow) {
- this._pendingReflow = false;
- this._reflow();
- }
- }
-
- scrollToIndex(index, position = 'start') {
- if (!Number.isFinite(index))
- return;
- index = Math.min(this.totalItems, Math.max(0, index));
- this._scrollToIndex = index;
- if (position === 'nearest') {
- position = index > this._first + this._num / 2 ? 'end' : 'start';
- }
- switch (position) {
- case 'start':
- this._scrollToAnchor = 0;
- break;
- case 'center':
- this._scrollToAnchor = 0.5;
- break;
- case 'end':
- this._scrollToAnchor = 1;
- break;
- default:
- throw new TypeError(
- 'position must be one of: start, center, end, nearest');
- }
- this._scheduleReflow();
- this.reflowIfNeeded();
- }
-
- ///
-
- _scheduleReflow() {
- this._pendingReflow = true;
- }
-
- _reflow() {
- const {_first, _last, _scrollSize} = this;
-
- this._updateScrollSize();
- this._getActiveItems();
- this._scrollIfNeeded();
-
- if (this._scrollSize !== _scrollSize) {
- this._emitScrollSize();
- }
-
- if (this._first === -1 && this._last === -1) {
- this._emitRange();
- } else if (
- this._first !== _first || this._last !== _last ||
- this._spacingChanged) {
- this._emitRange();
- this._emitChildPositions();
- }
- this._emitScrollError();
- }
-
- _updateScrollSize() {
- // Ensure we have at least 1px - this allows getting at least 1 item to be
- // rendered.
- this._scrollSize = Math.max(1, this._totalItems * this._delta);
- }
-
- _checkThresholds() {
- if (this._viewDim1 === 0 && this._num > 0) {
- this._scheduleReflow();
- } else {
- const min = Math.max(0, this._scrollPosition - this._overhang);
- const max = Math.min(
- this._scrollSize,
- this._scrollPosition + this._viewDim1 + this._overhang);
- if (this._physicalMin > min || this._physicalMax < max) {
- this._scheduleReflow();
- }
- }
- }
-
- _scrollIfNeeded() {
- if (this._scrollToIndex === -1) {
- return;
- }
- const index = this._scrollToIndex;
- const anchor = this._scrollToAnchor;
- const pos = this._getItemPosition(index)[this._positionDim];
- const size = this._getItemSize(index)[this._sizeDim];
-
- const curAnchorPos = this._scrollPosition + this._viewDim1 * anchor;
- const newAnchorPos = pos + size * anchor;
- // Ensure scroll position is an integer within scroll bounds.
- const scrollPosition = Math.floor(Math.min(
- this._scrollSize - this._viewDim1,
- Math.max(0, this._scrollPosition - curAnchorPos + newAnchorPos)));
- this._scrollError += this._scrollPosition - scrollPosition;
- this._scrollPosition = scrollPosition;
- }
-
- _emitRange(inProps) {
- const detail = Object.assign(
- {
- first: this._first,
- last: this._last,
- num: this._num,
- stable: true,
- },
- inProps);
- this.dispatchEvent(new CustomEvent('rangechange', {detail}));
- }
-
- _emitScrollSize() {
- const detail = {
- [this._sizeDim]: this._scrollSize,
- };
- this.dispatchEvent(new CustomEvent('scrollsizechange', {detail}));
- }
-
- _emitScrollError() {
- if (this._scrollError) {
- const detail = {
- [this._positionDim]: this._scrollError,
- [this._secondaryPositionDim]: 0,
- };
- this.dispatchEvent(new CustomEvent('scrollerrorchange', {detail}));
- this._scrollError = 0;
- }
- }
-
- _emitChildPositions() {
- const detail = {};
- for (let idx = this._first; idx <= this._last; idx++) {
- detail[idx] = this._getItemPosition(idx);
- }
- this.dispatchEvent(new CustomEvent('itempositionchange', {detail}));
- }
-
- _itemDim2Changed() {
- // Override
- }
-
- _viewDim2Changed() {
- // Override
- }
-
- _scrollPositionChanged(oldPos, newPos) {
- // When both values are bigger than the max scroll position, keep the
- // current _scrollToIndexx, otherwise invalidate it.
- const maxPos = this._scrollSize - this._viewDim1;
- if (oldPos < maxPos || newPos < maxPos) {
- this._scrollToIndex = -1;
- }
- }
-
- _getActiveItems() {
- // Override
- }
-
- _getItemPosition(idx) {
- // Override.
- }
-
- _getItemSize(idx) {
- // Override.
- return {
- [this._sizeDim]: this._itemDim1,
- [this._secondarySizeDim]: this._itemDim2,
- };
- }
-} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.mjs
deleted file mode 100644
index c9c00d021da..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.mjs
+++ /dev/null
@@ -1,64 +0,0 @@
-import Layout1dBase from './layout-1d-base.mjs';
-
-export default class Layout extends Layout1dBase {
- constructor(config) {
- super(config);
- this._rolumns = 1;
- }
-
- updateItemSizes(sizes) {
- // Assume all items have the same size.
- const size = Object.values(sizes)[0];
- if (size) {
- this.itemSize = size;
- }
- }
-
- _viewDim2Changed() {
- this._defineGrid();
- }
-
- _itemDim2Changed() {
- this._defineGrid();
- }
-
- _getActiveItems() {
- const min = Math.max(0, this._scrollPosition - this._overhang);
- const max = Math.min(
- this._scrollSize,
- this._scrollPosition + this._viewDim1 + this._overhang);
- const firstCow = Math.floor(min / this._delta);
- const lastCow = Math.ceil(max / this._delta) - 1;
-
- this._first = firstCow * this._rolumns;
- this._last =
- Math.min(((lastCow + 1) * this._rolumns) - 1, this._totalItems);
- this._physicalMin = this._delta * firstCow;
- this._physicalMax = this._delta * (lastCow + 1);
- }
-
- _getItemPosition(idx) {
- return {
- [this._positionDim]: Math.floor(idx / this._rolumns) * this._delta,
- [this._secondaryPositionDim]: this._spacing +
- ((idx % this._rolumns) * (this._spacing + this._itemDim2))
- }
- }
-
-
- _defineGrid() {
- const {_spacing} = this;
- this._rolumns = Math.max(1, Math.floor(this._viewDim2 / this._itemDim2));
- if (this._rolumns > 1) {
- this._spacing = (this._viewDim2 % (this._rolumns * this._itemDim2)) /
- (this._rolumns + 1);
- }
- this._spacingChanged = !(_spacing === this._spacing);
- this._scheduleReflow();
- }
-
- _updateScrollSize() {
- this._scrollSize =
- Math.max(1, Math.ceil(this._totalItems / this._rolumns) * this._delta);
- }
-} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.mjs
deleted file mode 100644
index 6f5d181cb0e..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.mjs
+++ /dev/null
@@ -1,349 +0,0 @@
-import Layout1dBase from './layout-1d-base.mjs';
-
-export default class Layout extends Layout1dBase {
- constructor(config) {
- super(config);
- this._physicalItems = new Map();
- this._newPhysicalItems = new Map();
-
- this._metrics = new Map();
-
- this._anchorIdx = null;
- this._anchorPos = null;
- this._stable = true;
-
- this._needsRemeasure = false;
-
- this._nMeasured = 0;
- this._tMeasured = 0;
-
- this._estimate = true;
- }
-
- updateItemSizes(sizes) {
- Object.keys(sizes).forEach((key) => {
- const metrics = sizes[key], mi = this._getMetrics(key),
- prevSize = mi[this._sizeDim];
-
- // TODO(valdrin) Handle margin collapsing.
- // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
- mi.width = metrics.width + (metrics.marginLeft || 0) +
- (metrics.marginRight || 0);
- mi.height = metrics.height + (metrics.marginTop || 0) +
- (metrics.marginBottom || 0);
-
- const size = mi[this._sizeDim];
- const item = this._getPhysicalItem(Number(key));
- if (item) {
- let delta;
-
- if (size !== undefined) {
- item.size = size;
- if (prevSize === undefined) {
- delta = size;
- this._nMeasured++;
- } else {
- delta = size - prevSize;
- }
- }
- this._tMeasured = this._tMeasured + delta;
- } else {
- // console.debug(`Could not find physical item for key ${key}`);
- }
- });
- if (!this._nMeasured) {
- console.warn(`No items measured yet.`);
- } else {
- this._updateItemSize();
- this._scheduleReflow();
- }
- }
-
- _updateItemSize() {
- // Keep integer values.
- this._itemSize[this._sizeDim] =
- Math.round(this._tMeasured / this._nMeasured);
- }
-
- //
-
- _getMetrics(idx) {
- return (this._metrics[idx] = this._metrics[idx] || {});
- }
-
- _getPhysicalItem(idx) {
- return this._newPhysicalItems.get(idx) || this._physicalItems.get(idx);
- }
-
- _getSize(idx) {
- const item = this._getPhysicalItem(idx);
- return item && item.size;
- }
-
- _getPosition(idx) {
- const item = this._physicalItems.get(idx);
- return item ? item.pos : (idx * (this._delta)) + this._spacing;
- }
-
- _calculateAnchor(lower, upper) {
- if (lower === 0) {
- return 0;
- }
- if (upper > this._scrollSize - this._viewDim1) {
- return this._maxIdx;
- }
- return Math.max(
- 0,
- Math.min(
- this._maxIdx, Math.floor(((lower + upper) / 2) / this._delta)));
- }
-
- _getAnchor(lower, upper) {
- if (this._physicalItems.size === 0) {
- return this._calculateAnchor(lower, upper);
- }
- if (this._first < 0) {
- console.error('_getAnchor: negative _first');
- return this._calculateAnchor(lower, upper);
- }
- if (this._last < 0) {
- console.error('_getAnchor: negative _last');
- return this._calculateAnchor(lower, upper);
- }
-
- const firstItem = this._getPhysicalItem(this._first),
- lastItem = this._getPhysicalItem(this._last),
- firstMin = firstItem.pos, firstMax = firstMin + firstItem.size,
- lastMin = lastItem.pos, lastMax = lastMin + lastItem.size;
-
- if (lastMax < lower) {
- // Window is entirely past physical items, calculate new anchor
- return this._calculateAnchor(lower, upper);
- }
- if (firstMin > upper) {
- // Window is entirely before physical items, calculate new anchor
- return this._calculateAnchor(lower, upper);
- }
- if (firstMin >= lower || firstMax >= lower) {
- // First physical item overlaps window, choose it
- return this._first;
- }
- if (lastMax <= upper || lastMin <= upper) {
- // Last physical overlaps window, choose it
- return this._last;
- }
- // Window contains a physical item, but not the first or last
- let maxIdx = this._last, minIdx = this._first;
-
- while (true) {
- let candidateIdx = Math.round((maxIdx + minIdx) / 2),
- candidate = this._physicalItems.get(candidateIdx),
- cMin = candidate.pos, cMax = cMin + candidate.size;
-
- if ((cMin >= lower && cMin <= upper) ||
- (cMax >= lower && cMax <= upper)) {
- return candidateIdx;
- } else if (cMax < lower) {
- minIdx = candidateIdx + 1;
- } else if (cMin > upper) {
- maxIdx = candidateIdx - 1;
- }
- }
- }
-
- _getActiveItems() {
- if (this._viewDim1 === 0 || this._totalItems === 0) {
- this._clearItems();
- } else {
- const upper = Math.min(
- this._scrollSize,
- this._scrollPosition + this._viewDim1 + this._overhang),
- lower = Math.max(0, upper - this._viewDim1 - (2 * this._overhang));
-
- this._getItems(lower, upper);
- }
- }
-
- _clearItems() {
- this._first = -1;
- this._last = -1;
- this._physicalMin = 0;
- this._physicalMax = 0;
- const items = this._newPhysicalItems;
- this._newPhysicalItems = this._physicalItems;
- this._newPhysicalItems.clear();
- this._physicalItems = items;
- this._stable = true;
- }
-
- _getItems(lower, upper) {
- const items = this._newPhysicalItems;
-
- // The anchorIdx is the anchor around which we reflow.
- // It is designed to allow jumping to any point of the scroll size.
- // We choose it once and stick with it until stable. first and last are
- // deduced around it.
- if (this._anchorIdx === null || this._anchorPos === null) {
- this._anchorIdx = this._getAnchor(lower, upper);
- this._anchorPos = this._getPosition(this._anchorIdx);
- }
-
- let anchorSize = this._getSize(this._anchorIdx);
- if (anchorSize === undefined) {
- anchorSize = this._itemDim1;
- }
-
- // Anchor might be outside bounds, so prefer correcting the error and keep
- // that anchorIdx.
- let anchorErr = 0;
-
- if (this._anchorPos + anchorSize + this._spacing < lower) {
- anchorErr = lower - (this._anchorPos + anchorSize + this._spacing);
- }
-
- if (this._anchorPos > upper) {
- anchorErr = upper - this._anchorPos;
- }
-
- if (anchorErr) {
- this._scrollPosition -= anchorErr;
- lower -= anchorErr;
- upper -= anchorErr;
- this._scrollError += anchorErr;
- }
-
- items.set(this._anchorIdx, {pos: this._anchorPos, size: anchorSize});
-
- this._first = (this._last = this._anchorIdx);
- this._physicalMin = (this._physicalMax = this._anchorPos);
-
- this._stable = true;
-
- while (this._physicalMin > lower && this._first > 0) {
- let size = this._getSize(--this._first);
- if (size === undefined) {
- this._stable = false;
- size = this._itemDim1;
- }
- const pos = (this._physicalMin -= size + this._spacing);
- items.set(this._first, {pos, size});
- if (this._stable === false && this._estimate === false) {
- break;
- }
- }
-
- while (this._physicalMax < upper && this._last < this._totalItems) {
- let size = this._getSize(this._last);
- if (size === undefined) {
- this._stable = false;
- size = this._itemDim1;
- }
- items.set(this._last++, {pos: this._physicalMax, size});
- if (this._stable === false && this._estimate === false) {
- break;
- } else {
- this._physicalMax += size + this._spacing;
- }
- }
-
- this._last--;
-
- // This handles the cases where we were relying on estimated sizes.
- const extentErr = this._calculateError();
- if (extentErr) {
- this._physicalMin -= extentErr;
- this._physicalMax -= extentErr;
- this._anchorPos -= extentErr;
- this._scrollPosition -= extentErr;
- items.forEach(item => item.pos -= extentErr);
- this._scrollError += extentErr;
- }
-
- if (this._stable) {
- this._newPhysicalItems = this._physicalItems;
- this._newPhysicalItems.clear();
- this._physicalItems = items;
- }
- }
-
- _calculateError() {
- if (this._first === 0) {
- return this._physicalMin;
- } else if (this._physicalMin <= 0) {
- return this._physicalMin - (this._first * this._delta);
- } else if (this._last === this._maxIdx) {
- return this._physicalMax - this._scrollSize;
- } else if (this._physicalMax >= this._scrollSize) {
- return (
- (this._physicalMax - this._scrollSize) +
- ((this._maxIdx - this._last) * this._delta));
- }
- return 0;
- }
-
- _updateScrollSize() {
- // Reuse previously calculated physical max, as it might be
- // higher than the estimated size.
- super._updateScrollSize();
- this._scrollSize = Math.max(this._physicalMax, this._scrollSize);
- }
-
- // TODO: Can this be made to inherit from base, with proper hooks?
- _reflow() {
- const {_first, _last, _scrollSize} = this;
-
- this._updateScrollSize();
- this._getActiveItems();
- this._scrollIfNeeded();
-
- if (this._scrollSize !== _scrollSize) {
- this._emitScrollSize();
- }
-
- this._emitRange();
- if (this._first === -1 && this._last === -1) {
- this._resetReflowState();
- } else if (
- this._first !== _first || this._last !== _last ||
- this._needsRemeasure) {
- this._emitChildPositions();
- this._emitScrollError();
- } else {
- this._emitChildPositions();
- this._emitScrollError();
- this._resetReflowState();
- }
- }
-
- _resetReflowState() {
- this._anchorIdx = null;
- this._anchorPos = null;
- this._stable = true;
- }
-
- _getItemPosition(idx) {
- return {
- [this._positionDim]: this._getPosition(idx),
- [this._secondaryPositionDim]: 0
- }
- }
-
- _getItemSize(idx) {
- return {
- [this._sizeDim]: this._getSize(idx) || this._itemDim1,
- [this._secondarySizeDim]: this._itemDim2,
- };
- }
-
- _viewDim2Changed() {
- this._needsRemeasure = true;
- this._scheduleReflow();
- }
-
- _emitRange() {
- const remeasure = this._needsRemeasure;
- const stable = this._stable;
- this._needsRemeasure = false;
- super._emitRange({remeasure, stable});
- }
-}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.mjs
deleted file mode 100644
index 3d3cb6aa7c1..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.mjs
+++ /dev/null
@@ -1,531 +0,0 @@
-export const Repeats = Superclass => class extends Superclass {
- constructor(config) {
- super();
-
- this._createElementFn = null;
- this._updateElementFn = null;
- this._recycleElementFn = null;
- this._elementKeyFn = null;
-
- this._measureCallback = null;
-
- this._totalItems = 0;
- // Consider renaming this. firstVisibleIndex?
- this._first = 0;
- // Consider renaming this. count? visibleElements?
- this._num = Infinity;
-
- this.__incremental = false;
-
- // used only internally..
- // legacy from 1st approach to preact integration
- this._manageDom = true;
- // used to check if it is more perf if you don't care of dom order?
- this._maintainDomOrder = true;
-
- this._last = 0;
- this._prevFirst = 0;
- this._prevLast = 0;
-
- this._needsReset = false;
- this._needsRemeasure = false;
- this._pendingRender = null;
-
- // Contains child nodes in the rendered order.
- this._ordered = [];
- // this._pool = [];
- this._active = new Map();
- this._prevActive = new Map();
- // Both used for recycling purposes.
- this._keyToChild = new Map();
- this._childToKey = new WeakMap();
- // Used to keep track of measures by index.
- this._indexToMeasure = {};
- // Used to debounce _measureChildren calls.
- this._measuringId = -1;
-
- if (config) {
- Object.assign(this, config);
- }
- }
-
- // API
-
- get container() {
- return this._container;
- }
- set container(container) {
- if (container === this._container) {
- return;
- }
- if (this._container) {
- // Remove children from old container.
- this._ordered.forEach((child) => this._removeChild(child));
- }
-
- this._container = container;
-
- if (container) {
- // Insert children in new container.
- this._ordered.forEach((child) => this._insertBefore(child, null));
- } else {
- this._ordered.length = 0;
- this._active.clear();
- this._prevActive.clear();
- }
- this.requestReset();
- }
-
- get createElement() {
- return this._createElementFn;
- }
- set createElement(fn) {
- if (fn !== this._createElementFn) {
- this._createElementFn = fn;
- this._keyToChild.clear();
- this.requestReset();
- }
- }
-
- get updateElement() {
- return this._updateElementFn;
- }
- set updateElement(fn) {
- if (fn !== this._updateElementFn) {
- this._updateElementFn = fn;
- this.requestReset();
- }
- }
-
- get recycleElement() {
- return this._recycleElementFn;
- }
- set recycleElement(fn) {
- if (fn !== this._recycleElementFn) {
- this._recycleElementFn = fn;
- this.requestReset();
- }
- }
-
- get elementKey() {
- return this._elementKeyFn;
- }
- set elementKey(fn) {
- if (fn !== this._elementKeyFn) {
- this._elementKeyFn = fn;
- this._keyToChild.clear();
- this.requestReset();
- }
- }
-
- get first() {
- return this._first;
- }
-
- set first(idx) {
- if (typeof idx === 'number') {
- const newFirst = Math.max(0, Math.min(idx, this._totalItems - this._num));
- if (newFirst !== this._first) {
- this._first = newFirst;
- this._scheduleRender();
- }
- }
- }
-
- get num() {
- return this._num;
- }
-
- set num(n) {
- if (typeof n === 'number') {
- if (n !== this._num) {
- this._num = n;
- this.first = this._first;
- this._scheduleRender();
- }
- }
- }
-
- get totalItems() {
- return this._totalItems;
- }
-
- set totalItems(num) {
- // TODO(valdrin) should we check if it is a finite number?
- // Technically, Infinity would break Layout, not VirtualRepeater.
- if (typeof num === 'number' && num !== this._totalItems) {
- this._totalItems = num;
- this.first = this._first;
- this.requestReset();
- }
- }
-
- get _incremental() {
- return this.__incremental;
- }
-
- set _incremental(inc) {
- if (inc !== this.__incremental) {
- this.__incremental = inc;
- this._scheduleRender();
- }
- }
-
- requestReset() {
- this._needsReset = true;
- this._scheduleRender();
- }
-
- requestRemeasure() {
- this._needsRemeasure = true;
- this._scheduleRender();
- }
-
- // Core functionality
-
- /**
- * @protected
- */
- _shouldRender() {
- return Boolean(this.container && this.createElement);
- }
-
- /**
- * @private
- */
- _scheduleRender() {
- if (!this._pendingRender) {
- this._pendingRender = requestAnimationFrame(() => {
- this._pendingRender = null;
- if (this._shouldRender()) {
- this._render();
- }
- });
- }
- }
-
- /**
- * Returns those children that are about to be displayed and that
- * require to be positioned. If reset or remeasure has been triggered,
- * all children are returned.
- * @return {{indices:Array<number>,children:Array<Element>}}
- * @private
- */
- get _toMeasure() {
- return this._ordered.reduce((toMeasure, c, i) => {
- const idx = this._first + i;
- if (this._needsReset || this._needsRemeasure || idx < this._prevFirst ||
- idx > this._prevLast) {
- toMeasure.indices.push(idx);
- toMeasure.children.push(c);
- }
- return toMeasure;
- }, {indices: [], children: []});
- }
-
- /**
- * Measures each child bounds and builds a map of index/bounds to be passed to
- * the `_measureCallback`
- * @private
- */
- _measureChildren({indices, children}) {
- let pm = children.map(
- (c, i) => this._indexToMeasure[indices[i]] || this._measureChild(c));
- const mm = /** @type {{ number: { width: number, height: number } }} */
- (pm.reduce((out, cur, i) => {
- out[indices[i]] = this._indexToMeasure[indices[i]] = cur;
- return out;
- }, {}));
- this._measureCallback(mm);
- }
-
- /**
- * @protected
- */
- _render() {
- const rangeChanged =
- this._first !== this._prevFirst || this._num !== this._prevNum;
- // Create/update/recycle DOM.
- if (rangeChanged || this._needsReset) {
- this._last =
- this._first + Math.min(this._num, this._totalItems - this._first) - 1;
- if (this._num || this._prevNum) {
- if (this._needsReset) {
- this._reset(this._first, this._last);
- } else {
- this._discardHead();
- this._discardTail();
- this._addHead();
- this._addTail();
- }
- }
- }
- if (this._needsRemeasure || this._needsReset) {
- this._indexToMeasure = {};
- }
- // Retrieve DOM to be measured.
- // Do it right before cleanup and reset of properties.
- const shouldMeasure = this._num > 0 && this._measureCallback &&
- (rangeChanged || this._needsRemeasure || this._needsReset);
- const toMeasure = shouldMeasure ? this._toMeasure : null;
-
- // Cleanup.
- if (!this._incremental) {
- this._prevActive.forEach((idx, child) => this._unassignChild(child, idx));
- this._prevActive.clear();
- }
- // Reset internal properties.
- this._prevFirst = this._first;
- this._prevLast = this._last;
- this._prevNum = this._num;
- this._needsReset = false;
- this._needsRemeasure = false;
-
- // Notify render completed.
- this._didRender();
- // Measure DOM.
- if (toMeasure) {
- this._measureChildren(toMeasure);
- }
- }
-
- /**
- * Invoked after DOM is updated, and before it gets measured.
- * @protected
- */
- _didRender() {
- }
-
- /**
- * @private
- */
- _discardHead() {
- const o = this._ordered;
- for (let idx = this._prevFirst; o.length && idx < this._first; idx++) {
- this._unassignChild(o.shift(), idx);
- }
- }
-
- /**
- * @private
- */
- _discardTail() {
- const o = this._ordered;
- for (let idx = this._prevLast; o.length && idx > this._last; idx--) {
- this._unassignChild(o.pop(), idx);
- }
- }
-
- /**
- * @private
- */
- _addHead() {
- const start = this._first;
- const end = Math.min(this._last, this._prevFirst - 1);
- for (let idx = end; idx >= start; idx--) {
- const child = this._assignChild(idx);
- if (this._manageDom) {
- if (this._maintainDomOrder || !this._childIsAttached(child)) {
- this._insertBefore(child, this._firstChild);
- }
- }
- if (this.updateElement) {
- this.updateElement(child, idx);
- }
- this._ordered.unshift(child);
- }
- }
-
- /**
- * @private
- */
- _addTail() {
- const start = Math.max(this._first, this._prevLast + 1);
- const end = this._last;
- for (let idx = start; idx <= end; idx++) {
- const child = this._assignChild(idx);
- if (this._manageDom) {
- if (this._maintainDomOrder || !this._childIsAttached(child)) {
- this._insertBefore(child, null);
- }
- }
- if (this.updateElement) {
- this.updateElement(child, idx);
- }
- this._ordered.push(child);
- }
- }
-
- /**
- * @param {number} first
- * @param {number} last
- * @private
- */
- _reset(first, last) {
- const len = last - first + 1;
- // Explain why swap prevActive with active - affects _assignChild.
- const prevActive = this._active;
- this._active = this._prevActive;
- this._prevActive = prevActive;
- let currentMarker = this._manageDom && this._firstChild;
- this._ordered.length = 0;
- for (let n = 0; n < len; n++) {
- const idx = first + n;
- const child = this._assignChild(idx);
- this._ordered.push(child);
- if (this._manageDom) {
- if (currentMarker && this._maintainDomOrder) {
- if (currentMarker === this._node(child)) {
- currentMarker = this._nextSibling(child);
- } else {
- this._insertBefore(child, currentMarker);
- }
- } else if (!this._childIsAttached(child)) {
- this._insertBefore(child, null);
- }
- }
- if (this.updateElement) {
- this.updateElement(child, idx);
- }
- }
- }
-
- /**
- * @param {number} idx
- * @private
- */
- _assignChild(idx) {
- const key = this.elementKey ? this.elementKey(idx) : idx;
- let child;
- if (child = this._keyToChild.get(key)) {
- this._prevActive.delete(child);
- } else {
- child = this.createElement(idx);
- this._keyToChild.set(key, child);
- this._childToKey.set(child, key);
- }
- this._showChild(child);
- this._active.set(child, idx);
- return child;
- }
-
- /**
- * @param {*} child
- * @param {number} idx
- * @private
- */
- _unassignChild(child, idx) {
- this._hideChild(child);
- if (this._incremental) {
- this._active.delete(child);
- this._prevActive.set(child, idx);
- } else {
- const key = this._childToKey.get(child);
- this._childToKey.delete(child);
- this._keyToChild.delete(key);
- this._active.delete(child);
- if (this.recycleElement) {
- this.recycleElement(child, idx);
- } else if (this._node(child).parentNode) {
- this._removeChild(child);
- }
- }
- }
-
- // TODO: Is this the right name?
- /**
- * @private
- */
- get _firstChild() {
- return this._ordered.length && this._childIsAttached(this._ordered[0]) ?
- this._node(this._ordered[0]) :
- null;
- }
-
- // Overridable abstractions for child manipulation
- /**
- * @protected
- */
- _node(child) {
- return child;
- }
- /**
- * @protected
- */
- _nextSibling(child) {
- return child.nextSibling;
- }
- /**
- * @protected
- */
- _insertBefore(child, referenceNode) {
- this._container.insertBefore(child, referenceNode);
- }
- /**
- * @protected
- */
- _childIsAttached(child) {
- const node = this._node(child);
- return node && node.parentNode === this._container;
- }
- /**
- * @protected
- */
- _hideChild(child) {
- if (child.style) {
- child.style.display = 'none';
- }
- }
- /**
- * @protected
- */
- _showChild(child) {
- if (child.style) {
- child.style.display = null;
- }
- }
-
- /**
- *
- * @param {!Element} child
- * @return {{width: number, height: number, marginTop: number, marginBottom: number, marginLeft: number, marginRight: number}} childMeasures
- * @protected
- */
- _measureChild(child) {
- // offsetWidth doesn't take transforms in consideration,
- // so we use getBoundingClientRect which does.
- const {width, height} = child.getBoundingClientRect();
- // console.debug(`_measureChild #${this._container.id} > #${
- // child.id}: height: ${height}px`);
- return Object.assign({width, height}, getMargins(child));
- }
-
- /**
- * Remove child.
- * Override to control child removal.
- *
- * @param {*} child
- * @protected
- */
- _removeChild(child) {
- child.parentNode.removeChild(child);
- }
-}
-
-function getMargins(el) {
- const style = window.getComputedStyle(el);
- // console.log(el.id, style.position);
- return {
- marginLeft: getMarginValue(style.marginLeft),
- marginRight: getMarginValue(style.marginRight),
- marginTop: getMarginValue(style.marginTop),
- marginBottom: getMarginValue(style.marginBottom),
- };
-}
-
-function getMarginValue(value) {
- value = value ? parseFloat(value) : NaN;
- return value !== value ? 0 : value;
-}
-
-export const VirtualRepeater = Repeats(class {}); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.mjs
deleted file mode 100644
index 049501e6ec9..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.mjs
+++ /dev/null
@@ -1,444 +0,0 @@
-import {Repeats} from './virtual-repeater.mjs';
-
-export class RangeChangeEvent extends Event {
- constructor(type, init) {
- super(type, init);
- this._first = Math.floor(init.first || 0);
- this._last = Math.floor(init.last || 0);
- }
- get first() {
- return this._first;
- }
- get last() {
- return this._last;
- }
-}
-
-export const RepeatsAndScrolls = Superclass => class extends Repeats
-(Superclass) {
- constructor(config) {
- super();
- this._num = 0;
- this._first = -1;
- this._last = -1;
- this._prevFirst = -1;
- this._prevLast = -1;
-
- this._needsUpdateView = false;
- this._containerElement = null;
- this._layout = null;
- this._scrollTarget = null;
- // Keep track of original inline style of the container,
- // so it can be restored when container is changed.
- this._containerInlineStyle = null;
- // A sentinel element that sizes the container when
- // it is a scrolling element.
- this._sizer = null;
- // Layout provides these values, we set them on _render().
- this._scrollSize = null;
- this._scrollErr = null;
- this._childrenPos = null;
-
- this._containerSize = null;
- this._containerRO = new ResizeObserver(
- (entries) => this._containerSizeChanged(entries[0].contentRect));
-
- this._skipNextChildrenSizeChanged = false;
- this._childrenRO =
- new ResizeObserver((entries) => this._childrenSizeChanged(entries));
-
- if (config) {
- Object.assign(this, config);
- }
- }
-
- get container() {
- return this._container;
- }
- set container(container) {
- super.container = container;
-
- const oldEl = this._containerElement;
- // Consider document fragments as shadowRoots.
- const newEl =
- (container && container.nodeType === Node.DOCUMENT_FRAGMENT_NODE) ?
- container.host :
- container;
- if (oldEl === newEl) {
- return;
- }
-
- this._containerRO.disconnect();
- this._containerSize = null;
-
- if (oldEl) {
- if (this._containerInlineStyle) {
- oldEl.setAttribute('style', this._containerInlineStyle);
- } else {
- oldEl.removeAttribute('style');
- }
- this._containerInlineStyle = null;
- if (oldEl === this._scrollTarget) {
- oldEl.removeEventListener('scroll', this, {passive: true});
- this._sizer && this._sizer.remove();
- }
- } else {
- // First time container was setup, add listeners only now.
- addEventListener('scroll', this, {passive: true});
- }
-
- this._containerElement = newEl;
-
- if (newEl) {
- this._containerInlineStyle = newEl.getAttribute('style') || null;
- if (newEl === this._scrollTarget) {
- this._sizer = this._sizer || this._createContainerSizer();
- this._container.prepend(this._sizer);
- }
- this._scheduleUpdateView();
- this._containerRO.observe(newEl);
- }
- }
-
- get layout() {
- return this._layout;
- }
- set layout(layout) {
- if (layout === this._layout) {
- return;
- }
-
- if (this._layout) {
- this._measureCallback = null;
- this._layout.removeEventListener('scrollsizechange', this);
- this._layout.removeEventListener('scrollerrorchange', this);
- this._layout.removeEventListener('itempositionchange', this);
- this._layout.removeEventListener('rangechange', this);
- // Reset container size so layout can get correct viewport size.
- if (this._containerElement) {
- this._sizeContainer();
- }
- }
-
- this._layout = layout;
-
- if (this._layout) {
- if (typeof this._layout.updateItemSizes === 'function') {
- this._measureCallback = this._layout.updateItemSizes.bind(this._layout);
- this.requestRemeasure();
- }
- this._layout.addEventListener('scrollsizechange', this);
- this._layout.addEventListener('scrollerrorchange', this);
- this._layout.addEventListener('itempositionchange', this);
- this._layout.addEventListener('rangechange', this);
- this._scheduleUpdateView();
- }
- }
-
- /**
- * The element that generates scroll events and defines the container
- * viewport. The value `null` (default) corresponds to `window` as scroll
- * target.
- * @type {Element|null}
- */
- get scrollTarget() {
- return this._scrollTarget;
- }
- /**
- * @param {Element|null} target
- */
- set scrollTarget(target) {
- // Consider window as null.
- if (target === window) {
- target = null;
- }
- if (this._scrollTarget === target) {
- return;
- }
- if (this._scrollTarget) {
- this._scrollTarget.removeEventListener('scroll', this, {passive: true});
- if (this._sizer && this._scrollTarget === this._containerElement) {
- this._sizer.remove();
- }
- }
-
- this._scrollTarget = target;
-
- if (target) {
- target.addEventListener('scroll', this, {passive: true});
- if (target === this._containerElement) {
- this._sizer = this._sizer || this._createContainerSizer();
- this._container.prepend(this._sizer);
- }
- }
- }
-
- /**
- * @protected
- */
- _render() {
- // console.time(`render ${this._containerElement.localName}#${
- // this._containerElement.id}`);
-
- this._childrenRO.disconnect();
-
- // Update layout properties before rendering to have correct
- // first, num, scroll size, children positions.
- this._layout.totalItems = this.totalItems;
- if (this._needsUpdateView) {
- this._needsUpdateView = false;
- this._updateView();
- }
- this._layout.reflowIfNeeded();
- // Keep rendering until there is no more scheduled renders.
- while (true) {
- if (this._pendingRender) {
- cancelAnimationFrame(this._pendingRender);
- this._pendingRender = null;
- }
- // Update scroll size and correct scroll error before rendering.
- this._sizeContainer(this._scrollSize);
- if (this._scrollErr) {
- // This triggers a 'scroll' event (async) which triggers another
- // _updateView().
- this._correctScrollError(this._scrollErr);
- this._scrollErr = null;
- }
- // Position children (_didRender()), and provide their measures to layout.
- super._render();
- this._layout.reflowIfNeeded();
- // If layout reflow did not provoke another render, we're done.
- if (!this._pendingRender) {
- break;
- }
- }
- // We want to skip the first ResizeObserver callback call as we already
- // measured the children.
- this._skipNextChildrenSizeChanged = true;
- this._kids.forEach(child => this._childrenRO.observe(child));
-
- // console.timeEnd(`render ${this._containerElement.localName}#${
- // this._containerElement.id}`);
- }
-
- /**
- * Position children before they get measured.
- * Measuring will force relayout, so by positioning
- * them first, we reduce computations.
- * @protected
- */
- _didRender() {
- if (this._childrenPos) {
- this._positionChildren(this._childrenPos);
- this._childrenPos = null;
- }
- }
-
- /**
- * @param {!Event} event
- * @private
- */
- handleEvent(event) {
- switch (event.type) {
- case 'scroll':
- if (!this._scrollTarget || event.target === this._scrollTarget) {
- this._scheduleUpdateView();
- }
- break;
- case 'scrollsizechange':
- this._scrollSize = event.detail;
- this._scheduleRender();
- break;
- case 'scrollerrorchange':
- this._scrollErr = event.detail;
- this._scheduleRender();
- break;
- case 'itempositionchange':
- this._childrenPos = event.detail;
- this._scheduleRender();
- break;
- case 'rangechange':
- this._adjustRange(event.detail);
- break;
- default:
- console.warn('event not handled', event);
- }
- }
- /**
- * @return {!Element}
- * @private
- */
- _createContainerSizer() {
- const sizer = document.createElement('div');
- // When the scrollHeight is large, the height
- // of this element might be ignored.
- // Setting content and font-size ensures the element
- // has a size.
- Object.assign(sizer.style, {
- position: 'absolute',
- margin: '-2px 0 0 0',
- padding: 0,
- visibility: 'hidden',
- fontSize: '2px',
- });
- sizer.innerHTML = '&nbsp;';
- return sizer;
- }
-
- // Rename _ordered to _kids?
- /**
- * @protected
- */
- get _kids() {
- return this._ordered;
- }
- /**
- * @private
- */
- _scheduleUpdateView() {
- this._needsUpdateView = true;
- this._scheduleRender();
- }
- /**
- * @private
- */
- _updateView() {
- let width, height, top, left;
- if (this._scrollTarget === this._containerElement) {
- width = this._containerSize.width;
- height = this._containerSize.height;
- left = this._containerElement.scrollLeft;
- top = this._containerElement.scrollTop;
- } else {
- const containerBounds = this._containerElement.getBoundingClientRect();
- const scrollBounds = this._scrollTarget ?
- this._scrollTarget.getBoundingClientRect() :
- {top: 0, left: 0, width: innerWidth, height: innerHeight};
- const scrollerWidth = scrollBounds.width;
- const scrollerHeight = scrollBounds.height;
- const xMin = Math.max(
- 0, Math.min(scrollerWidth, containerBounds.left - scrollBounds.left));
- const yMin = Math.max(
- 0, Math.min(scrollerHeight, containerBounds.top - scrollBounds.top));
- const xMax = this._layout.direction === 'vertical' ?
- Math.max(
- 0,
- Math.min(
- scrollerWidth, containerBounds.right - scrollBounds.left)) :
- scrollerWidth;
- const yMax = this._layout.direction === 'vertical' ?
- scrollerHeight :
- Math.max(
- 0,
- Math.min(
- scrollerHeight, containerBounds.bottom - scrollBounds.top));
- width = xMax - xMin;
- height = yMax - yMin;
- left = Math.max(0, -(containerBounds.x - scrollBounds.left));
- top = Math.max(0, -(containerBounds.y - scrollBounds.top));
- }
- this._layout.viewportSize = {width, height};
- this._layout.viewportScroll = {top, left};
- }
- /**
- * @private
- */
- _sizeContainer(size) {
- if (this._scrollTarget === this._containerElement) {
- const left = size && size.width ? size.width - 1 : 0;
- const top = size && size.height ? size.height - 1 : 0;
- this._sizer.style.transform = `translate(${left}px, ${top}px)`;
- } else {
- const style = this._containerElement.style;
- style.minWidth = size && size.width ? size.width + 'px' : null;
- style.minHeight = size && size.height ? size.height + 'px' : null;
- }
- }
- /**
- * @private
- */
- _positionChildren(pos) {
- const kids = this._kids;
- Object.keys(pos).forEach(key => {
- const idx = key - this._first;
- const child = kids[idx];
- if (child) {
- const {top, left} = pos[key];
- // console.debug(`_positionChild #${this._container.id} >
- // #${child.id}: top ${top}`);
- child.style.position = 'absolute';
- child.style.transform = `translate(${left}px, ${top}px)`;
- }
- });
- }
- /**
- * @private
- */
- _adjustRange(range) {
- this.num = range.num;
- this.first = range.first;
- this._incremental = !(range.stable);
- if (range.remeasure) {
- this.requestRemeasure();
- } else if (range.stable) {
- this._notifyStable();
- }
- }
- /**
- * @protected
- */
- _shouldRender() {
- if (!super._shouldRender() || !this._layout) {
- return false;
- }
- // NOTE: we're about to render, but the ResizeObserver didn't execute yet.
- // Since we want to keep rAF timing, we compute _containerSize now.
- // Would be nice to have a way to flush ResizeObservers
- if (this._containerSize === null) {
- const {width, height} = this._containerElement.getBoundingClientRect();
- this._containerSize = {width, height};
- }
- return this._containerSize.width > 0 || this._containerSize.height > 0;
- }
- /**
- * @private
- */
- _correctScrollError(err) {
- if (this._scrollTarget) {
- this._scrollTarget.scrollTop -= err.top;
- this._scrollTarget.scrollLeft -= err.left;
- } else {
- window.scroll(window.scrollX - err.left, window.scrollY - err.top);
- }
- }
- /**
- * @protected
- */
- _notifyStable() {
- const {first, num} = this;
- const last = first + num - 1;
- this._container.dispatchEvent(
- new RangeChangeEvent('rangechange', {first, last}));
- }
- /**
- * @private
- */
- _containerSizeChanged(size) {
- const {width, height} = size;
- this._containerSize = {width, height};
- // console.debug('container changed size', this._containerSize);
- this._scheduleUpdateView();
- }
- /**
- * @private
- */
- _childrenSizeChanged() {
- if (this._skipNextChildrenSizeChanged) {
- this._skipNextChildrenSizeChanged = false;
- } else {
- this.requestRemeasure();
- }
- }
-};
-
-export const VirtualScroller = RepeatsAndScrolls(class {});
diff --git a/chromium/third_party/blink/renderer/core/script/script.h b/chromium/third_party/blink/renderer/core/script/script.h
index 2e99f96cb9c..d7951dc1f0a 100644
--- a/chromium/third_party/blink/renderer/core/script/script.h
+++ b/chromium/third_party/blink/renderer/core/script/script.h
@@ -21,7 +21,7 @@ class WorkerGlobalScope;
// https://html.spec.whatwg.org/C/#concept-script
class CORE_EXPORT Script : public GarbageCollectedFinalized<Script> {
public:
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(Visitor* visitor) {}
virtual ~Script() {}
diff --git a/chromium/third_party/blink/renderer/core/script/script_loader.cc b/chromium/third_party/blink/renderer/core/script/script_loader.cc
index 41d5609b5f2..4666d857aed 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.cc
@@ -33,7 +33,6 @@
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/imports/html_import.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -52,7 +51,8 @@
#include "third_party/blink/renderer/core/script/script_runner.h"
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string.h"
-#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
@@ -71,7 +71,8 @@ ScriptLoader::ScriptLoader(ScriptElementBase* element,
bool already_started)
: element_(element),
will_be_parser_executed_(false),
- will_execute_when_document_finished_parsing_(false) {
+ will_execute_when_document_finished_parsing_(false),
+ force_deferred_(false) {
// <spec href="https://html.spec.whatwg.org/C/#already-started">... The
// cloning steps for script elements must set the "already started" flag on
// the copy if it is set on the element being cloned.</spec>
@@ -97,7 +98,7 @@ ScriptLoader::ScriptLoader(ScriptElementBase* element,
ScriptLoader::~ScriptLoader() {}
-void ScriptLoader::Trace(blink::Visitor* visitor) {
+void ScriptLoader::Trace(Visitor* visitor) {
visitor->Trace(element_);
visitor->Trace(pending_script_);
visitor->Trace(prepared_pending_script_);
@@ -279,17 +280,17 @@ bool ScriptLoader::BlockForNoModule(mojom::ScriptType script_type,
// https://html.spec.whatwg.org/C/#prepare-a-script
// - Step 6 of obtaining a preloaded module script
// https://html.spec.whatwg.org/C/#link-type-modulepreload.
-network::mojom::FetchCredentialsMode ScriptLoader::ModuleScriptCredentialsMode(
+network::mojom::CredentialsMode ScriptLoader::ModuleScriptCredentialsMode(
CrossOriginAttributeValue cross_origin) {
switch (cross_origin) {
case kCrossOriginAttributeNotSet:
case kCrossOriginAttributeAnonymous:
- return network::mojom::FetchCredentialsMode::kSameOrigin;
+ return network::mojom::CredentialsMode::kSameOrigin;
case kCrossOriginAttributeUseCredentials:
- return network::mojom::FetchCredentialsMode::kInclude;
+ return network::mojom::CredentialsMode::kInclude;
}
NOTREACHED();
- return network::mojom::FetchCredentialsMode::kOmit;
+ return network::mojom::CredentialsMode::kOmit;
}
// https://github.com/WICG/feature-policy/issues/135
@@ -449,7 +450,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// <spec step="17">Let module script credentials mode be the module script
// credentials mode for the element's crossorigin content attribute.</spec>
- network::mojom::FetchCredentialsMode credentials_mode =
+ network::mojom::CredentialsMode credentials_mode =
ModuleScriptCredentialsMode(cross_origin);
// <spec step="18">Let cryptographic nonce be the element's
@@ -583,7 +584,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// <spec step="24.6.B">"module"
//
- // Fetch a module script graph given url, settings object, "script", and
+ // Fetch an external module script graph given url, settings object, and
// options.</spec>
Modulator* modulator = Modulator::From(
ToScriptStateForMainWorld(context_document->GetFrame()));
@@ -623,7 +624,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// <spec step="25.2">Switch on the script's type:</spec>
switch (GetScriptType()) {
- // <spec step="25.2.A">"classic"</spec>
+ // <spec step="25.2.A">"classic"</spec>
case mojom::ScriptType::kClassic: {
// <spec step="25.2.A.1">Let script be the result of creating a classic
// script using source text, settings object, base URL, and
@@ -650,28 +651,38 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
break;
}
- // <spec step="25.2.B">"module"</spec>
+ // <spec step="25.2.B">"module"</spec>
case mojom::ScriptType::kModule: {
- // <spec step="25.2.B.1">Let script be the result of creating a module
- // script using source text, settings object, base URL, and
- // options.</spec>
+ // <spec step="25.2.B.1">Fetch an inline module script graph, given
+ // source text, base URL, settings object, and options. When this
+ // asynchronously completes, set the script's script to the result. At
+ // that time, the script is ready.</spec>
+ //
+ // <specdef label="fetch-an-inline-module-script-graph"
+ // href="https://html.spec.whatwg.org/C/#fetch-an-inline-module-script-graph">
const KURL& source_url = element_document.Url();
Modulator* modulator = Modulator::From(
ToScriptStateForMainWorld(context_document->GetFrame()));
+
+ // <spec label="fetch-an-inline-module-script-graph" step="1">Let script
+ // be the result of creating a JavaScript module script using source
+ // text, settings object, base URL, and options.</spec>
ModuleScript* module_script = JSModuleScript::Create(
ParkableString(element_->TextFromChildren().Impl()), nullptr,
ScriptSourceLocationType::kInline, modulator, source_url, base_url,
options, position);
- // <spec step="25.2.B.2">If this returns null, set the script's script
- // to null and return; the script is ready.</spec>
+ // <spec label="fetch-an-inline-module-script-graph" step="2">If script
+ // is null, asynchronously complete this algorithm with null, and abort
+ // these steps.</spec>
if (!module_script)
return false;
- // <spec step="25.2.B.3">Fetch the descendants of and instantiate
- // script, given settings object and the destination "script". When this
- // asynchronously completes, set the script's script to the result. At
- // that time, the script is ready.</spec>
+ // <spec label="fetch-an-inline-module-script-graph" step="4">Fetch the
+ // descendants of and instantiate script, given settings object, the
+ // destination "script", and visited set. When this asynchronously
+ // completes with final result, asynchronously complete this algorithm
+ // with final result.</spec>
auto* module_tree_client =
MakeGarbageCollected<ModulePendingScriptTreeClient>();
modulator->FetchDescendantsForInlineScript(
@@ -718,6 +729,25 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
return true;
}
+ // Check for external script that should be force deferred.
+ if (GetScriptType() == mojom::ScriptType::kClassic &&
+ element_->HasSourceAttribute() &&
+ context_document->GetFrame()->ShouldForceDeferScript() &&
+ context_document->IsHTMLDocument() && parser_inserted_ &&
+ !element_->AsyncAttributeValue()) {
+ // In terms of ScriptLoader flags, force deferred scripts behave like
+ // parser-blocking scripts, except that |force_deferred_| is set.
+ // The caller of PrepareScript()
+ // - Force-defers such scripts if the caller supports force-defer
+ // (i.e., HTMLParserScriptRunner); or
+ // - Ignores the |force_deferred_| flag and handles such scripts as
+ // parser-blocking scripts (e.g., XMLParserScriptRunner).
+ force_deferred_ = true;
+ will_be_parser_executed_ = true;
+
+ return true;
+ }
+
// <spec step="26.B">If the script's type is "classic", and the element has a
// src attribute, and the element has been flagged as "parser-inserted", and
// the element does not have an async attribute ...</spec>
@@ -793,6 +823,14 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
DCHECK_EQ(GetScriptType(), mojom::ScriptType::kClassic);
DCHECK(!is_external_script_);
+ // Check for inline script that should be force deferred.
+ if (context_document->GetFrame()->ShouldForceDeferScript() &&
+ context_document->IsHTMLDocument() && parser_inserted_) {
+ force_deferred_ = true;
+ will_be_parser_executed_ = true;
+ return true;
+ }
+
// <spec step="26.E">If the element does not have a src attribute, and the
// element has been flagged as "parser-inserted", and either the parser that
// created the script is an XML parser or it's an HTML parser whose script
@@ -861,7 +899,7 @@ void ScriptLoader::FetchModuleScriptTree(
const ScriptFetchOptions& options) {
// <spec step="24.6.B">"module"
//
- // Fetch a module script graph given url, settings object, "script", and
+ // Fetch an external module script graph given url, settings object, and
// options.</spec>
auto* module_tree_client =
MakeGarbageCollected<ModulePendingScriptTreeClient>();
@@ -880,23 +918,6 @@ PendingScript* ScriptLoader::TakePendingScript(
EnumerationHistogram, scheduling_type_histogram,
("Blink.Script.SchedulingType", kLastScriptSchedulingType + 1));
scheduling_type_histogram.Count(static_cast<int>(scheduling_type));
-
- switch (scheduling_type) {
- case ScriptSchedulingType::kAsync:
- case ScriptSchedulingType::kInOrder:
- // As ClassicPendingScript keeps a reference to ScriptResource,
- // the ScriptResource is anyway kept alive until evaluation,
- // and can be garbage-collected after that (together with
- // ClassicPendingScript).
- resource_keep_alive_ = nullptr;
- break;
-
- default:
- // ScriptResource is kept alive by resource_keep_alive_
- // until ScriptLoader is garbage collected.
- break;
- }
-
PendingScript* pending_script = prepared_pending_script_;
prepared_pending_script_ = nullptr;
pending_script->SetSchedulingType(scheduling_type);
@@ -908,6 +929,19 @@ void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) {
DCHECK_EQ(pending_script_, pending_script);
DCHECK_EQ(pending_script_->GetScriptType(), GetScriptType());
DCHECK(pending_script->IsControlledByScriptRunner());
+ DCHECK(pending_script_->GetSchedulingType() == ScriptSchedulingType::kAsync ||
+ pending_script_->GetSchedulingType() ==
+ ScriptSchedulingType::kInOrder);
+ // Historically we clear |resource_keep_alive_| when the scheduling type is
+ // kAsync or kInOrder (crbug.com/778799). But if the script resource was
+ // served via signed exchange, the script may not be in the HTTPCache,
+ // therefore will need to be refetched over network if it's evicted from the
+ // memory cache not be in the HTTPCache. So we keep |resource_keep_alive_| to
+ // keep the resource in the memory cache.
+ if (resource_keep_alive_ &&
+ !resource_keep_alive_->GetResponse().IsSignedExchangeInnerResponse()) {
+ resource_keep_alive_ = nullptr;
+ }
Document* context_document = element_->GetDocument().ContextDocument();
if (!context_document) {
diff --git a/chromium/third_party/blink/renderer/core/script/script_loader.h b/chromium/third_party/blink/renderer/core/script/script_loader.h
index ae9e7b85a7a..0ac49da3bc0 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.h
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.h
@@ -56,7 +56,7 @@ class CORE_EXPORT ScriptLoader final
public:
ScriptLoader(ScriptElementBase*, bool created_by_parser, bool is_evaluated);
~ScriptLoader() override;
- void Trace(blink::Visitor*) override;
+ void Trace(Visitor*) override;
const char* NameInHeapSnapshot() const override { return "ScriptLoader"; }
enum LegacyTypeSupport {
@@ -78,7 +78,7 @@ class CORE_EXPORT ScriptLoader final
static bool BlockForNoModule(mojom::ScriptType, bool nomodule);
- static network::mojom::FetchCredentialsMode ModuleScriptCredentialsMode(
+ static network::mojom::CredentialsMode ModuleScriptCredentialsMode(
CrossOriginAttributeValue);
// https://html.spec.whatwg.org/C/#prepare-a-script
@@ -96,6 +96,7 @@ class CORE_EXPORT ScriptLoader final
bool WillExecuteWhenDocumentFinishedParsing() const {
return will_execute_when_document_finished_parsing_;
}
+ bool IsForceDeferred() const { return force_deferred_; }
bool IsParserInserted() const { return parser_inserted_; }
bool AlreadyStarted() const { return already_started_; }
bool IsNonBlocking() const { return non_blocking_; }
@@ -145,33 +146,27 @@ class CORE_EXPORT ScriptLoader final
// https://html.spec.whatwg.org/C/#script-processing-model
// "A script element has several associated pieces of state.":
- // <spec
- // href="https://html.spec.whatwg.org/C/#already-started">
- // ... Initially, script elements must have this flag unset ...</spec>
+ // <spec href="https://html.spec.whatwg.org/C/#already-started">... Initially,
+ // script elements must have this flag unset ...</spec>
bool already_started_ = false;
- // <spec
- // href="https://html.spec.whatwg.org/C/#parser-inserted">
- // ... Initially, script elements must have this flag unset. ...</spec>
+ // <spec href="https://html.spec.whatwg.org/C/#parser-inserted">... Initially,
+ // script elements must have this flag unset. ...</spec>
bool parser_inserted_ = false;
- // <spec
- // href="https://html.spec.whatwg.org/C/#non-blocking">
- // ... Initially, script elements must have this flag set. ...</spec>
+ // <spec href="https://html.spec.whatwg.org/C/#non-blocking">... Initially,
+ // script elements must have this flag set. ...</spec>
bool non_blocking_ = true;
- // <spec
- // href="https://html.spec.whatwg.org/C/#ready-to-be-parser-executed">
+ // <spec href="https://html.spec.whatwg.org/C/#ready-to-be-parser-executed">
// ... Initially, script elements must have this flag unset ...</spec>
bool ready_to_be_parser_executed_ = false;
- // <spec
- // href="https://html.spec.whatwg.org/C/#concept-script-type">
- // ... It is determined when the script is prepared, ...</spec>
+ // <spec href="https://html.spec.whatwg.org/C/#concept-script-type">... It is
+ // determined when the script is prepared, ...</spec>
mojom::ScriptType script_type_ = mojom::ScriptType::kClassic;
- // <spec
- // href="https://html.spec.whatwg.org/C/#concept-script-external">
+ // <spec href="https://html.spec.whatwg.org/C/#concept-script-external">
// ... It is determined when the script is prepared, ...</spec>
bool is_external_script_ = false;
@@ -180,6 +175,9 @@ class CORE_EXPORT ScriptLoader final
bool will_execute_when_document_finished_parsing_;
+ // The script will be force deferred (https://crbug.com/976061).
+ bool force_deferred_;
+
// A PendingScript is first created in PrepareScript() and stored in
// |prepared_pending_script_|.
// Later, TakePendingScript() is called, and its caller holds a reference
diff --git a/chromium/third_party/blink/renderer/core/script/script_runner.cc b/chromium/third_party/blink/renderer/core/script/script_runner.cc
index 6e76a6417ec..c3e12f4ab8f 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.cc
@@ -256,7 +256,7 @@ void ScriptRunner::ExecuteTask() {
#endif
}
-void ScriptRunner::Trace(blink::Visitor* visitor) {
+void ScriptRunner::Trace(Visitor* visitor) {
visitor->Trace(document_);
visitor->Trace(pending_in_order_scripts_);
visitor->Trace(pending_async_scripts_);
diff --git a/chromium/third_party/blink/renderer/core/script/script_runner.h b/chromium/third_party/blink/renderer/core/script/script_runner.h
index 54ad3d801f9..75b69989ca9 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.h
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.h
@@ -58,7 +58,7 @@ class CORE_EXPORT ScriptRunner final
static void MovePendingScript(Document&, Document&, ScriptLoader*);
- void Trace(blink::Visitor*);
+ void Trace(Visitor*);
const char* NameInHeapSnapshot() const override { return "ScriptRunner"; }
private:
diff --git a/chromium/third_party/blink/renderer/core/script/script_scheduling_type.h b/chromium/third_party/blink/renderer/core/script/script_scheduling_type.h
index 928143ec895..744f0af5e93 100644
--- a/chromium/third_party/blink/renderer/core/script/script_scheduling_type.h
+++ b/chromium/third_party/blink/renderer/core/script/script_scheduling_type.h
@@ -62,7 +62,14 @@ enum class ScriptSchedulingType {
kAsync,
// Inline <script> executed immediately within prepare-a-script.
- kImmediate
+ kImmediate,
+
+ // Force deferred scripts controlled by HTMLParserScriptRunner.
+ // These are otherwise parser-blocking scripts that are being forced to
+ // execute after parsing completes (due to a ForceDeferScriptIntervention).
+ //
+ // Spec: not yet spec'ed. https://crbug.com/976061
+ kForceDefer
};
static const int kLastScriptSchedulingType =
diff --git a/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc b/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
new file mode 100644
index 00000000000..8ee3c96acf6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
@@ -0,0 +1,153 @@
+// 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.
+
+#include "third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h"
+
+#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
+#include "third_party/blink/renderer/core/script/modulator.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+ValueWrapperSyntheticModuleScript*
+ValueWrapperSyntheticModuleScript::CreateJSONWrapperSyntheticModuleScript(
+ const base::Optional<ModuleScriptCreationParams>& params,
+ Modulator* settings_object,
+ const ScriptFetchOptions options_) {
+ DCHECK(settings_object->HasValidContext());
+ ScriptState::Scope scope(settings_object->GetScriptState());
+ v8::Local<v8::Context> context =
+ settings_object->GetScriptState()->GetContext();
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::TryCatch try_catch(isolate);
+ v8::Local<v8::String> original_json =
+ V8String(isolate, params->GetSourceText().ToString());
+ v8::Local<v8::Value> parsed_json;
+ ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
+ "ModuleScriptLoader",
+ "CreateJSONWrapperSyntheticModuleScript");
+ // Step 1. "Let script be a new module script that this algorithm will
+ // subsequently initialize."
+ // [spec text]
+ // Step 2. "Set script's settings object to settings."
+ // [spec text]
+ // Step 3. "Set script's base URL and fetch options to null."
+ // [spec text]
+ // Step 4. "Set script's parse error and error to rethrow to null."
+ // [spec text]
+ // Step 5. "Let json be ? Call(%JSONParse%, undefined, « source »).
+ // If this throws an exception, set script's parse error to that exception,
+ // and return script."
+ // [spec text]
+ if (!v8::JSON::Parse(context, original_json).ToLocal(&parsed_json)) {
+ DCHECK(try_catch.HasCaught());
+ exception_state.RethrowV8Exception(try_catch.Exception());
+ v8::Local<v8::Value> error = exception_state.GetException();
+ exception_state.ClearException();
+ return ValueWrapperSyntheticModuleScript::CreateWithError(
+ parsed_json, settings_object, params->GetResponseUrl(),
+ params->GetResponseUrl(), options_, error);
+ } else {
+ return ValueWrapperSyntheticModuleScript::CreateWithDefaultExport(
+ parsed_json, settings_object, params->GetResponseUrl(),
+ params->GetResponseUrl(), options_);
+ }
+}
+
+ValueWrapperSyntheticModuleScript*
+ValueWrapperSyntheticModuleScript::CreateWithDefaultExport(
+ v8::Local<v8::Value> value,
+ Modulator* settings_object,
+ const KURL& source_url,
+ const KURL& base_url,
+ const ScriptFetchOptions& fetch_options,
+ const TextPosition& start_position) {
+ v8::Isolate* isolate = settings_object->GetScriptState()->GetIsolate();
+ std::vector<v8::Local<v8::String>> export_names{V8String(isolate, "default")};
+ v8::Local<v8::Module> v8_synthetic_module = v8::Module::CreateSyntheticModule(
+ isolate, V8String(isolate, source_url.GetString()), export_names,
+ ValueWrapperSyntheticModuleScript::EvaluationSteps);
+ // Step 6. "Set script's record to the result of creating a synthetic module
+ // record with a default export of json with settings."
+ // [spec text]
+ ModuleRecord record = ModuleRecord(isolate, v8_synthetic_module, source_url);
+
+ ValueWrapperSyntheticModuleScript* value_wrapper_module_script =
+ MakeGarbageCollected<ValueWrapperSyntheticModuleScript>(
+ settings_object, record, source_url, base_url, fetch_options, value,
+ start_position);
+ settings_object->GetModuleRecordResolver()->RegisterModuleScript(
+ value_wrapper_module_script);
+ // Step 7. "Return script."
+ // [spec text]
+ return value_wrapper_module_script;
+}
+
+ValueWrapperSyntheticModuleScript*
+ValueWrapperSyntheticModuleScript::CreateWithError(
+ v8::Local<v8::Value> value,
+ Modulator* settings_object,
+ const KURL& source_url,
+ const KURL& base_url,
+ const ScriptFetchOptions& fetch_options,
+ v8::Local<v8::Value> error,
+ const TextPosition& start_position) {
+ ValueWrapperSyntheticModuleScript* value_wrapper_module_script =
+ MakeGarbageCollected<ValueWrapperSyntheticModuleScript>(
+ settings_object, ModuleRecord(), source_url, base_url, fetch_options,
+ value, start_position);
+ settings_object->GetModuleRecordResolver()->RegisterModuleScript(
+ value_wrapper_module_script);
+ value_wrapper_module_script->SetParseErrorAndClearRecord(
+ ScriptValue(settings_object->GetScriptState(), error));
+ // Step 7. "Return script."
+ // [spec text]
+ return value_wrapper_module_script;
+}
+
+ValueWrapperSyntheticModuleScript::ValueWrapperSyntheticModuleScript(
+ Modulator* settings_object,
+ ModuleRecord record,
+ const KURL& source_url,
+ const KURL& base_url,
+ const ScriptFetchOptions& fetch_options,
+ v8::Local<v8::Value> value,
+ const TextPosition& start_position)
+ : ModuleScript(settings_object,
+ record,
+ source_url,
+ base_url,
+ fetch_options),
+ export_value_(v8::Isolate::GetCurrent(), value) {}
+
+// TODO(sasebree) Implement this method
+v8::MaybeLocal<v8::Value> ValueWrapperSyntheticModuleScript::EvaluationSteps(
+ v8::Local<v8::Context> context,
+ v8::Local<v8::Module> module) {
+ NOTREACHED();
+ return v8::MaybeLocal<v8::Value>();
+}
+
+String ValueWrapperSyntheticModuleScript::InlineSourceTextForCSP() const {
+ // We don't construct a ValueWrapperSyntheticModuleScript with the original
+ // source, but instead construct it from the originally parsed
+ // text. If a need arises for the original module source to be used later,
+ // ValueWrapperSyntheticModuleScript will need to be modified such that its
+ // constructor takes this source text as an additional parameter and stashes
+ // it on the ValueWrapperSyntheticModuleScript.
+ NOTREACHED();
+ return "";
+}
+
+void ValueWrapperSyntheticModuleScript::Trace(Visitor* visitor) {
+ visitor->Trace(export_value_);
+ ModuleScript::Trace(visitor);
+}
+
+} // namespace blink \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h b/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h
new file mode 100644
index 00000000000..ae19c095cd9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h
@@ -0,0 +1,78 @@
+// 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.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_VALUE_WRAPPER_SYNTHETIC_MODULE_SCRIPT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_VALUE_WRAPPER_SYNTHETIC_MODULE_SCRIPT_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/script/module_script.h"
+
+namespace WTF {
+class TextPosition;
+} // namespace WTF
+
+namespace blink {
+
+class KURL;
+class Modulator;
+class ModuleScriptCreationParams;
+
+// ValueWrapperSyntheticModuleScript is a module script
+// (https://html.spec.whatwg.org/C/#module-script) that default-exports a single
+// v8::Value, for example JSON Module Script:
+// https://html.spec.whatwg.org/multipage/webappapis.html#json-module-script
+class CORE_EXPORT ValueWrapperSyntheticModuleScript final
+ : public ModuleScript {
+ public:
+ static ValueWrapperSyntheticModuleScript*
+ CreateJSONWrapperSyntheticModuleScript(
+ const base::Optional<ModuleScriptCreationParams>& params,
+ Modulator* settings_object,
+ const ScriptFetchOptions options_);
+
+ static ValueWrapperSyntheticModuleScript* CreateWithDefaultExport(
+ v8::Local<v8::Value> value,
+ Modulator* settings_object,
+ const KURL& source_url,
+ const KURL& base_url,
+ const ScriptFetchOptions& fetch_options,
+ const TextPosition& start_position = TextPosition::MinimumPosition());
+
+ static ValueWrapperSyntheticModuleScript* CreateWithError(
+ v8::Local<v8::Value> value,
+ Modulator* settings_object,
+ const KURL& source_url,
+ const KURL& base_url,
+ const ScriptFetchOptions& fetch_options,
+ v8::Local<v8::Value> error,
+ const TextPosition& start_position = TextPosition::MinimumPosition());
+
+ ValueWrapperSyntheticModuleScript(Modulator* settings_object,
+ ModuleRecord record,
+ const KURL& source_url,
+ const KURL& base_url,
+ const ScriptFetchOptions& fetch_options,
+ v8::Local<v8::Value> value,
+ const TextPosition& start_position);
+
+ // <specdef
+ // href="https://heycam.github.io/webidl/#synthetic-module-record">
+ // An abstract operation that will be performed upon evaluation of the module,
+ // taking the Synthetic Module Record as its sole argument. These will usually
+ // set up the exported values, by using SetSyntheticModuleExport. They must
+ // not modify [[ExportNames]]. They may return an abrupt completion.
+ static v8::MaybeLocal<v8::Value> EvaluationSteps(
+ v8::Local<v8::Context> context,
+ v8::Local<v8::Module> module);
+
+ String InlineSourceTextForCSP() const override;
+ void Trace(blink::Visitor* visitor) override;
+
+ private:
+ TraceWrapperV8Reference<v8::Value> export_value_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_VALUE_WRAPPER_SYNTHETIC_MODULE_SCRIPT_H_ \ No newline at end of file