WebKit Bugzilla
Attachment 350178 Details for
Bug 184307
: Custom elements in a reaction queue can lose its JS wrapper and become HTMLUnknownElement
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Fixes the bug
bug-184307-20180920004733.patch (text/plain), 20.00 KB, created by
Ryosuke Niwa
on 2018-09-20 00:47:34 PDT
(
hide
)
Description:
Fixes the bug
Filename:
MIME Type:
Creator:
Ryosuke Niwa
Created:
2018-09-20 00:47:34 PDT
Size:
20.00 KB
patch
obsolete
>Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 236246) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,47 @@ >+2018-09-20 Ryosuke Niwa <rniwa@webkit.org> >+ >+ Custom elements in a reaction queue can lose its JS wrapper and become HTMLUnknownElement >+ https://bugs.webkit.org/show_bug.cgi?id=184307 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ The bug was caused by the custom elements reaction queue not reporting its content to GC during marking. >+ >+ When there is no JS reference to the JS wrappers of those custom element, and if those custom elements >+ are disconnected, GC would happily collect those the wrappers. Unfortunately, the same bug exists for >+ any asynchronous events and other WebCore code which keeps elements alive for a later use but doesn't >+ report them to GC (e.g. during visitChildren). >+ >+ This patch, therefore, introduces a generic mechanism to keep these elements' wrappers alive. Namely, >+ we introduce StrongNodeRef, a new smart pointer type for Node's subclasses, which keeps element as well >+ as its wrappers alive. StrongNodeRef works by adding its Node to a global hash counted set when it's >+ created and making JSNodeOwner::isReachableFromOpaqueRoots return true when the node is in the set. >+ >+ Test: fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper.html >+ >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ * bindings/js/JSNodeCustom.cpp: >+ (WebCore::isReachableFromDOM): >+ * dom/CustomElementReactionQueue.cpp: >+ (WebCore::CustomElementReactionQueue::ElementQueue::invokeAll): Don't swap the vector of elements in >+ in the queue. Assuming each DOM API has an appropriate CustomElementsReactionStack, we should never >+ append a new element to this queue while invoking custom element reactions. >+ * dom/CustomElementReactionQueue.h: >+ * dom/StrongNodeRef.cpp: Added. >+ * dom/StrongNodeRef.h: Added. >+ (WebCore::StrongNodeRefMap::contains): Added. >+ (WebCore::StrongNodeRefMap::add): Added. >+ (WebCore::StrongNodeRefMap::remove): Added. >+ (WebCore::StrongNodeRef::StrongNodeRef): Added. We need isNull() check since WTFMove may have been >+ called on the source StrongNodeRef. >+ (WebCore::StrongNodeRef::~StrongNodeRef): Ditto. >+ (WebCore::StrongNodeRef::operator-> const): Added. >+ (WebCore::StrongNodeRef::get const): Added. >+ (WebCore::StrongNodeRef::operator T& const): Added. >+ (WebCore::StrongNodeRef::operator! const): Added. >+ (WebCore::StrongNodeRef::isNull const): Added. Returns true if WTFMove had been called on Ref. >+ > 2018-09-19 Ryosuke Niwa <rniwa@webkit.org> > > Improve node statistics for rare data >Index: Source/WebCore/Sources.txt >=================================================================== >--- Source/WebCore/Sources.txt (revision 236207) >+++ Source/WebCore/Sources.txt (working copy) >@@ -814,6 +814,7 @@ dom/SpectreGadget.cpp > dom/StaticNodeList.cpp > dom/StaticRange.cpp > dom/StringCallback.cpp >+dom/StrongNodeRef.cpp > dom/StyledElement.cpp > dom/TagCollection.cpp > dom/TemplateContentDocumentFragment.cpp >Index: Source/WebCore/WebCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/WebCore/WebCore.xcodeproj/project.pbxproj (revision 236207) >+++ Source/WebCore/WebCore.xcodeproj/project.pbxproj (working copy) >@@ -2839,6 +2839,7 @@ > 9B6C41531344949000085B62 /* StringWithDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B6C41521344949000085B62 /* StringWithDirection.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 9B714E211C91166900AC0E92 /* EventPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B714E1F1C91166900AC0E92 /* EventPath.h */; }; > 9BA273F4172206BB0097CE47 /* LogicalSelectionOffsetCaches.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */; }; >+ 9BAAC45C21520128003D4A98 /* StrongNodeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BAAC4562151E39E003D4A98 /* StrongNodeRef.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 9BAB6C6C12550631001626D4 /* EditingStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BAB6C6A12550631001626D4 /* EditingStyle.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 9BAF3B2412C1A39800014BF1 /* WritingDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BAF3B2312C1A39800014BF1 /* WritingDirection.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 9BBA2CAB1F679E0C00FD1C1E /* WebContentReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BF433761F67619B00E1FD71 /* WebContentReader.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -10861,6 +10862,8 @@ > 9B9299B01F6796A4006723C2 /* WebContentReaderCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebContentReaderCocoa.mm; sourceTree = "<group>"; }; > 9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogicalSelectionOffsetCaches.h; sourceTree = "<group>"; }; > 9BA827781F06156500F71E75 /* NavigationDisabler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigationDisabler.h; sourceTree = "<group>"; }; >+ 9BAAC4562151E39E003D4A98 /* StrongNodeRef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StrongNodeRef.h; sourceTree = "<group>"; }; >+ 9BAAC4582151E77A003D4A98 /* StrongNodeRef.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StrongNodeRef.cpp; sourceTree = "<group>"; }; > 9BAB6C6A12550631001626D4 /* EditingStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingStyle.h; sourceTree = "<group>"; }; > 9BAB6C6B12550631001626D4 /* EditingStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditingStyle.cpp; sourceTree = "<group>"; }; > 9BAF3B2312C1A39800014BF1 /* WritingDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WritingDirection.h; sourceTree = "<group>"; }; >@@ -23951,8 +23954,8 @@ > 2D0B4AA918DA1CCD00434DE1 /* IOSurface.h */, > 2D0B4AAA18DA1CCD00434DE1 /* IOSurface.mm */, > AD9FF6E01908391D003B61E0 /* IOSurfacePoolCocoa.mm */, >- CDC48AC72149CF2A0024FD59 /* MediaEngineConfigurationFactoryCocoa.h */, > CDC48AC82149CF2A0024FD59 /* MediaEngineConfigurationFactoryCocoa.cpp */, >+ CDC48AC72149CF2A0024FD59 /* MediaEngineConfigurationFactoryCocoa.h */, > 526724F21CB2FDF60075974D /* TextTrackRepresentationCocoa.h */, > 526724F11CB2FDF60075974D /* TextTrackRepresentationCocoa.mm */, > 2D3EF4441917915C00034184 /* WebActionDisablingCALayerDelegate.h */, >@@ -24730,8 +24733,8 @@ > CD669D651D232DF4004D1866 /* cocoa */ = { > isa = PBXGroup; > children = ( >- 417F7AEA2139BF6400FBA7EC /* MediaSessionManagerCocoa.mm */, > 417F7AED2139BF6500FBA7EC /* MediaSessionManagerCocoa.h */, >+ 417F7AEA2139BF6400FBA7EC /* MediaSessionManagerCocoa.mm */, > 417F7AEB2139BF6400FBA7EC /* WebAudioBufferList.cpp */, > 417F7AEC2139BF6500FBA7EC /* WebAudioBufferList.h */, > ); >@@ -26571,6 +26574,8 @@ > 8102C5871325BB1100DDE67A /* StringCallback.cpp */, > 81AC6C35131C57D30009A7E0 /* StringCallback.h */, > 81AC6C34131C57C20009A7E0 /* StringCallback.idl */, >+ 9BAAC4582151E77A003D4A98 /* StrongNodeRef.cpp */, >+ 9BAAC4562151E39E003D4A98 /* StrongNodeRef.h */, > A8C4A7EC09D563270003AC8D /* StyledElement.cpp */, > A8C4A7EB09D563270003AC8D /* StyledElement.h */, > C99058121E32B7340073BDDA /* SuccessOr.h */, >@@ -29472,6 +29477,7 @@ > 2D9BF7061DBFBB24007A7D99 /* MediaEncryptedEvent.h in Headers */, > 2D9BF7081DBFBB24007A7D99 /* MediaEncryptedEventInit.h in Headers */, > 41B28B151F8501D300FB52AC /* MediaEndpointConfiguration.h in Headers */, >+ CDC48AC92149CF2A0024FD59 /* MediaEngineConfigurationFactoryCocoa.h in Headers */, > E44613AD0CD6331000FADA75 /* MediaError.h in Headers */, > 4E1959220A39DABA00220FE5 /* MediaFeatureNames.h in Headers */, > 07A6D1EC1491137700051D0C /* MediaFragmentURIParser.h in Headers */, >@@ -30286,7 +30292,6 @@ > 517A534F1F54A8BA00DCDC0A /* ServiceWorkerRegistrationData.h in Headers */, > 517A53291F4B90B900DCDC0A /* ServiceWorkerRegistrationKey.h in Headers */, > 51F175691F3EBC8300C74950 /* ServiceWorkerRegistrationOptions.h in Headers */, >- CDC48AC92149CF2A0024FD59 /* MediaEngineConfigurationFactoryCocoa.h in Headers */, > 51BCCE301F8F179E006BA0ED /* ServiceWorkerThread.h in Headers */, > 4112B5431F9F9CA000E67875 /* ServiceWorkerThreadProxy.h in Headers */, > 515E37F61FAA940200D7F22A /* ServiceWorkerTypes.h in Headers */, >@@ -30403,6 +30408,7 @@ > ECA680C71E67724500731D20 /* StringUtilities.h in Headers */, > 9B6C41531344949000085B62 /* StringWithDirection.h in Headers */, > 849F77760EFEC6200090849D /* StrokeStyleApplier.h in Headers */, >+ 9BAAC45C21520128003D4A98 /* StrongNodeRef.h in Headers */, > 414B82051D6DF0E50077EBE3 /* StructuredClone.h in Headers */, > BC5EB6A30E81DC4F00B25965 /* StyleBackgroundData.h in Headers */, > BC5EB67B0E81D3BE00B25965 /* StyleBoxData.h in Headers */, >Index: Source/WebCore/bindings/js/JSNodeCustom.cpp >=================================================================== >--- Source/WebCore/bindings/js/JSNodeCustom.cpp (revision 236207) >+++ Source/WebCore/bindings/js/JSNodeCustom.cpp (working copy) >@@ -61,6 +61,7 @@ > #include "SVGElement.h" > #include "ScriptState.h" > #include "ShadowRoot.h" >+#include "StrongNodeRef.h" > #include "StyleSheet.h" > #include "StyledElement.h" > #include "Text.h" >@@ -107,6 +108,11 @@ static inline bool isReachableFromDOM(No > *reason = "Node which is firing event listeners"; > return true; > } >+ if (StrongNodeRefMap::contains(*node)) { >+ if (UNLIKELY(reason)) >+ *reason = "Node is scheduled to be used in an async script invocation)"; >+ return true; >+ } > } > > if (UNLIKELY(reason)) >Index: Source/WebCore/dom/CustomElementReactionQueue.cpp >=================================================================== >--- Source/WebCore/dom/CustomElementReactionQueue.cpp (revision 236207) >+++ Source/WebCore/dom/CustomElementReactionQueue.cpp (working copy) >@@ -234,15 +234,14 @@ inline void CustomElementReactionQueue:: > { > RELEASE_ASSERT(!m_invoking); > SetForScope<bool> invoking(m_invoking, true); >- Vector<Ref<Element>> elements; >- elements.swap(m_elements); >- RELEASE_ASSERT(m_elements.isEmpty()); >- for (auto& element : elements) { >+ auto originalSize = m_elements.size(); >+ for (auto& element : m_elements) { > auto* queue = element->reactionQueue(); > ASSERT(queue); > queue->invokeAll(element.get()); > } >- RELEASE_ASSERT(m_elements.isEmpty()); >+ RELEASE_ASSERT(m_elements.size() == originalSize); >+ m_elements.clear(); > } > > inline void CustomElementReactionQueue::ElementQueue::processQueue(JSC::ExecState* state) >Index: Source/WebCore/dom/CustomElementReactionQueue.h >=================================================================== >--- Source/WebCore/dom/CustomElementReactionQueue.h (revision 236207) >+++ Source/WebCore/dom/CustomElementReactionQueue.h (working copy) >@@ -25,6 +25,7 @@ > > #pragma once > >+#include "StrongNodeRef.h" > #include <wtf/Forward.h> > #include <wtf/Noncopyable.h> > #include <wtf/Vector.h> >@@ -71,7 +72,7 @@ public: > private: > void invokeAll(); > >- Vector<Ref<Element>> m_elements; >+ Vector<StrongNodeRef<Element>> m_elements; > bool m_invoking { false }; > }; > >Index: Source/WebCore/dom/StrongNodeRef.cpp >=================================================================== >--- Source/WebCore/dom/StrongNodeRef.cpp (nonexistent) >+++ Source/WebCore/dom/StrongNodeRef.cpp (working copy) >@@ -0,0 +1,39 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "StrongNodeRef.h" >+ >+#include <wtf/NeverDestroyed.h> >+ >+namespace WebCore { >+ >+HashCountedSet<Node*>& StrongNodeRefMap::map() >+{ >+ static NeverDestroyed<HashCountedSet<Node*>> map; >+ return map; >+} >+ >+} // namespace WebCore >Index: Source/WebCore/dom/StrongNodeRef.h >=================================================================== >--- Source/WebCore/dom/StrongNodeRef.h (nonexistent) >+++ Source/WebCore/dom/StrongNodeRef.h (working copy) >@@ -0,0 +1,91 @@ >+/* >+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include <wtf/DumbPtrTraits.h> >+#include <wtf/HashCountedSet.h> >+#include <wtf/Ref.h> >+ >+namespace WebCore { >+ >+class Node; >+ >+class StrongNodeRefMap { >+public: >+ static inline bool contains(Node& node) { return map().contains(&node); } >+ static inline void add(Node& node) { map().add(&node); } >+ static inline void remove(Node& node) { map().remove(&node); } >+ >+private: >+ static HashCountedSet<Node*>& map(); >+}; >+ >+template <typename T, typename = std::enable_if_t<std::is_same<T, typename std::remove_const<T>::type>::value>> >+class StrongNodeRef { >+ WTF_MAKE_NONCOPYABLE(StrongNodeRef); >+public: >+ >+ template<typename = std::enable_if_t<std::is_base_of<Node, T>::value>> >+ StrongNodeRef(T& object) >+ : m_ref(object) >+ { >+ StrongNodeRefMap::add(m_ref.get()); >+ } >+ >+ ~StrongNodeRef() >+ { >+ if (!isNull()) >+ StrongNodeRefMap::remove(m_ref.get()); >+ } >+ >+ template<typename X, typename Y, typename = std::enable_if_t<std::is_base_of<Node, T>::value>> >+ StrongNodeRef(Ref<X, Y>&& other) >+ : m_ref(WTFMove(other.m_ref)) >+ { >+ if (!isNull()) >+ StrongNodeRefMap::add(m_ref.get()); >+ } >+ >+ StrongNodeRef(StrongNodeRef&& other) >+ : m_ref(WTFMove(other.m_ref)) >+ { >+ } >+ >+ template<typename X, typename Y> StrongNodeRef(const StrongNodeRef<X, Y>& other) = delete; >+ >+ T* operator->() const { ASSERT(!isNull()); return m_ref.ptr(); } >+ T* ptr() const RETURNS_NONNULL { ASSERT(!isNull()); return m_ref.ptr(); } >+ T& get() const { ASSERT(!isNull()); return m_ref.get(); } >+ operator T&() const { ASSERT(!isNull()); return m_ref.get(); } >+ bool operator!() const { ASSERT(!isNull()); return !m_ref.get(); } >+ >+private: >+ bool isNull() const { return m_ref.isHashTableEmptyValue(); } >+ >+ Ref<T> m_ref; >+}; >+ >+} >Index: LayoutTests/ChangeLog >=================================================================== >--- LayoutTests/ChangeLog (revision 236207) >+++ LayoutTests/ChangeLog (working copy) >@@ -1,3 +1,16 @@ >+2018-09-20 Ryosuke Niwa <rniwa@webkit.org> >+ >+ Custom elements in a reaction queue can lose its JS wrapper and become HTMLUnknownElement >+ https://bugs.webkit.org/show_bug.cgi?id=184307 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Added a test for enqueuing a lot of custom elements into the reaction queue via innerHTML setter. >+ WebKit should retain the JS wrappers of all custom elements. >+ >+ * fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper-expected.txt: Added. >+ * fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper.html: Added. >+ > 2018-09-19 Youenn Fablet <youenn@apple.com> > > Implement sender/receiver getStats >Index: LayoutTests/fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper-expected.txt >=================================================================== >--- LayoutTests/fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper-expected.txt (nonexistent) >+++ LayoutTests/fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper-expected.txt (working copy) >@@ -0,0 +1,24 @@ >+This tests enqueuing a lot of custom elements during innerHTML. >+WebKit should not lose JS wrappers of those custom elements. >+ >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+ >Index: LayoutTests/fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper.html >=================================================================== >--- LayoutTests/fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper.html (nonexistent) >+++ LayoutTests/fast/custom-elements/custom-elements-reaction-queue-retains-js-wrapper.html (working copy) >@@ -0,0 +1,40 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<p>This tests enqueuing a lot of custom elements during innerHTML.<br> >+WebKit should not lose JS wrappers of those custom elements.</p> >+<pre id="log"></pre> >+<div id="container"><script> >+let failCount = 0; >+class MyComponent extends HTMLElement { >+ disconnectedCallback() { >+ if (!(this instanceof MyComponent)) >+ failCount++; >+ const x = new Array(100); >+ for (let i = 0; i < 100; i++) >+ x[i] = new Array(10); >+ } >+} >+customElements.define("my-component", MyComponent); >+ >+if (window.testRunner) >+ testRunner.dumpAsText(); >+ >+let content = ''; >+for (let i = 0; i < 50; i++) >+ content += '<my-component></my-component>'; >+content += '<my-component id="last"></my-component>' >+ >+let first = true; >+for (let test = 0; test < 20; test++) { >+ failCount = 0; >+ for (let i = 0; i < 10; i++) >+ document.getElementById('container').innerHTML = content; >+ document.getElementById('log').append(failCount ? `FAIL - ${failCount} elements lost wrappers\n` : 'PASS\n'); >+} >+document.getElementById('container').textContent = ''; >+ >+</script></div> >+</body> >+</html> >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
keith_miller
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 184307
:
337178
|
345910
|
349736
|
349740
|
349844
|
350093
|
350146
|
350157
| 350178