mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	browser(firefox): misc fixes (#983)
- crash support; - keydown supports text by committing composition; - cross-page frame handling; - security check for node adoption.
This commit is contained in:
		
							parent
							
								
									d367a2ed3a
								
							
						
					
					
						commit
						c2ab1e31f7
					
				@ -1 +1 @@
 | 
			
		||||
1028
 | 
			
		||||
1029
 | 
			
		||||
 | 
			
		||||
@ -1450,10 +1450,10 @@ index 0000000000000000000000000000000000000000..66f61d432f9ad2f50931b780ec5ea0e3
 | 
			
		||||
+this.NetworkObserver = NetworkObserver;
 | 
			
		||||
diff --git a/testing/juggler/TargetRegistry.js b/testing/juggler/TargetRegistry.js
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..2b1a1bd0f931d82824a86ecbb46f86483177a4e0
 | 
			
		||||
index 0000000000000000000000000000000000000000..6a128959f9128a87cd3d46a5d906028ff500f9e0
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/testing/juggler/TargetRegistry.js
 | 
			
		||||
@@ -0,0 +1,214 @@
 | 
			
		||||
@@ -0,0 +1,232 @@
 | 
			
		||||
+const {EventEmitter} = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
 | 
			
		||||
+const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
 | 
			
		||||
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 | 
			
		||||
@ -1506,6 +1506,7 @@ index 0000000000000000000000000000000000000000..2b1a1bd0f931d82824a86ecbb46f8648
 | 
			
		||||
+      target.dispose();
 | 
			
		||||
+      this.emit(TargetRegistry.Events.TargetDestroyed, target.info());
 | 
			
		||||
+    });
 | 
			
		||||
+    Services.obs.addObserver(this, 'oop-frameloader-crashed');
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async newPage({browserContextId}) {
 | 
			
		||||
@ -1563,6 +1564,22 @@ index 0000000000000000000000000000000000000000..2b1a1bd0f931d82824a86ecbb46f8648
 | 
			
		||||
+    this.emit(TargetRegistry.Events.TargetCreated, target.info());
 | 
			
		||||
+    return target;
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  observe(subject, topic, data) {
 | 
			
		||||
+    if (topic === 'oop-frameloader-crashed') {
 | 
			
		||||
+      const browser = subject.ownerElement;
 | 
			
		||||
+      if (!browser)
 | 
			
		||||
+        return;
 | 
			
		||||
+      const tab = this._mainWindow.gBrowser.getTabForBrowser(browser);
 | 
			
		||||
+      if (!tab)
 | 
			
		||||
+        return;
 | 
			
		||||
+      const target = this._tabToTarget.get(tab);
 | 
			
		||||
+      if (!target)
 | 
			
		||||
+        return;
 | 
			
		||||
+      this.emit(TargetRegistry.Events.TargetCrashed, target.id());
 | 
			
		||||
+      return;
 | 
			
		||||
+    }
 | 
			
		||||
+  }
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+class PageTarget {
 | 
			
		||||
@ -1663,6 +1680,7 @@ index 0000000000000000000000000000000000000000..2b1a1bd0f931d82824a86ecbb46f8648
 | 
			
		||||
+  TargetCreated: Symbol('TargetRegistry.Events.TargetCreated'),
 | 
			
		||||
+  TargetDestroyed: Symbol('TargetRegistry.Events.TargetDestroyed'),
 | 
			
		||||
+  TargetChanged: Symbol('TargetRegistry.Events.TargetChanged'),
 | 
			
		||||
+  TargetCrashed: Symbol('TargetRegistry.Events.TargetCrashed'),
 | 
			
		||||
+  PageTargetReady: Symbol('TargetRegistry.Events.PageTargetReady'),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
@ -1890,10 +1908,10 @@ index 0000000000000000000000000000000000000000..3891da101e6906ae2a3888e256aefd03
 | 
			
		||||
+
 | 
			
		||||
diff --git a/testing/juggler/content/FrameTree.js b/testing/juggler/content/FrameTree.js
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574bee5915ea
 | 
			
		||||
index 0000000000000000000000000000000000000000..6735dd39c6cfb6f945d5d094cfb7902f4eb9cefd
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/testing/juggler/content/FrameTree.js
 | 
			
		||||
@@ -0,0 +1,252 @@
 | 
			
		||||
@@ -0,0 +1,266 @@
 | 
			
		||||
+"use strict";
 | 
			
		||||
+const Ci = Components.interfaces;
 | 
			
		||||
+const Cr = Components.results;
 | 
			
		||||
@ -1907,6 +1925,12 @@ index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574b
 | 
			
		||||
+class FrameTree {
 | 
			
		||||
+  constructor(rootDocShell, waitForInitialNavigation) {
 | 
			
		||||
+    EventEmitter.decorate(this);
 | 
			
		||||
+
 | 
			
		||||
+    this._browsingContextGroup = rootDocShell.browsingContext.group;
 | 
			
		||||
+    if (!this._browsingContextGroup.__jugglerFrameTrees)
 | 
			
		||||
+      this._browsingContextGroup.__jugglerFrameTrees = new Set();
 | 
			
		||||
+    this._browsingContextGroup.__jugglerFrameTrees.add(this);
 | 
			
		||||
+
 | 
			
		||||
+    this._docShellToFrame = new Map();
 | 
			
		||||
+    this._frameIdToFrame = new Map();
 | 
			
		||||
+    this._pageReady = !waitForInitialNavigation;
 | 
			
		||||
@ -1928,6 +1952,13 @@ index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574b
 | 
			
		||||
+    ];
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  allFramesInBrowsingContextGroup(group) {
 | 
			
		||||
+    const frames = [];
 | 
			
		||||
+    for (const frameTree of (group.__jugglerFrameTrees || []))
 | 
			
		||||
+      frames.push(...frameTree.frames());
 | 
			
		||||
+    return frames;
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  isPageReady() {
 | 
			
		||||
+    return this._pageReady;
 | 
			
		||||
+  }
 | 
			
		||||
@ -1957,6 +1988,7 @@ index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574b
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  dispose() {
 | 
			
		||||
+    this._browsingContextGroup.__jugglerFrameTrees.delete(this);
 | 
			
		||||
+    helper.removeListeners(this._eventListeners);
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
@ -2148,7 +2180,7 @@ index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574b
 | 
			
		||||
+
 | 
			
		||||
diff --git a/testing/juggler/content/NetworkMonitor.js b/testing/juggler/content/NetworkMonitor.js
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..2508cce41565023b7fee9c7b85afe8ecebd26e7d
 | 
			
		||||
index 0000000000000000000000000000000000000000..be70ea364f9534bb3b344f64970366c32e8c11be
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/testing/juggler/content/NetworkMonitor.js
 | 
			
		||||
@@ -0,0 +1,62 @@
 | 
			
		||||
@ -2179,7 +2211,7 @@ index 0000000000000000000000000000000000000000..2508cce41565023b7fee9c7b85afe8ec
 | 
			
		||||
+    if (!loadContext)
 | 
			
		||||
+      return;
 | 
			
		||||
+    const window = loadContext.associatedWindow;
 | 
			
		||||
+    const frame = this._frameTree.frameForDocShell(window.docShell)
 | 
			
		||||
+    const frame = this._frameTree.frameForDocShell(window.docShell);
 | 
			
		||||
+    if (!frame)
 | 
			
		||||
+      return;
 | 
			
		||||
+    this._requestDetails.set(httpChannel.channelId, {
 | 
			
		||||
@ -2216,10 +2248,10 @@ index 0000000000000000000000000000000000000000..2508cce41565023b7fee9c7b85afe8ec
 | 
			
		||||
+
 | 
			
		||||
diff --git a/testing/juggler/content/PageAgent.js b/testing/juggler/content/PageAgent.js
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631f0bd1780
 | 
			
		||||
index 0000000000000000000000000000000000000000..994b683a78c43f8fb072cc185f2e5f8d2badec3c
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/testing/juggler/content/PageAgent.js
 | 
			
		||||
@@ -0,0 +1,875 @@
 | 
			
		||||
@@ -0,0 +1,912 @@
 | 
			
		||||
+"use strict";
 | 
			
		||||
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 | 
			
		||||
+const Ci = Components.interfaces;
 | 
			
		||||
@ -2734,6 +2766,11 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
 | 
			
		||||
+      throw new Error('Failed to find frame with id = ' + frameId);
 | 
			
		||||
+    const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
 | 
			
		||||
+    const context = this._runtime.findExecutionContext(executionContextId);
 | 
			
		||||
+    const fromPrincipal = unsafeObject.nodePrincipal;
 | 
			
		||||
+    const toFrame = this._frameTree.frame(context.auxData().frameId);
 | 
			
		||||
+    const toPrincipal = toFrame.domWindow().document.nodePrincipal;
 | 
			
		||||
+    if (!toPrincipal.subsumes(fromPrincipal))
 | 
			
		||||
+      return { remoteObject: null };
 | 
			
		||||
+    return { remoteObject: context.rawValueToRemoteObject(unsafeObject) };
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
@ -2771,9 +2808,20 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
 | 
			
		||||
+    if (!frame)
 | 
			
		||||
+      throw new Error('Failed to find frame with id = ' + frameId);
 | 
			
		||||
+    const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
 | 
			
		||||
+    const browsingContextGroup = frame.docShell().browsingContext.group;
 | 
			
		||||
+    const frames = this._frameTree.allFramesInBrowsingContextGroup(browsingContextGroup);
 | 
			
		||||
+    let contentFrame;
 | 
			
		||||
+    let ownerFrame;
 | 
			
		||||
+    for (const frame of frames) {
 | 
			
		||||
+      if (unsafeObject.contentWindow && frame.docShell() === unsafeObject.contentWindow.docShell)
 | 
			
		||||
+        contentFrame = frame;
 | 
			
		||||
+      const document = frame.domWindow().document;
 | 
			
		||||
+      if (unsafeObject === document || unsafeObject.ownerDocument === document)
 | 
			
		||||
+        ownerFrame = frame;
 | 
			
		||||
+    }
 | 
			
		||||
+    return {
 | 
			
		||||
+      contentFrameId: unsafeObject.contentWindow ? this._frameTree.frameForDocShell(unsafeObject.contentWindow.docShell).id() : undefined,
 | 
			
		||||
+      ownerFrameId: this._findFrameForNode(unsafeObject)._frame.id(),
 | 
			
		||||
+      contentFrameId: contentFrame ? contentFrame.id() : undefined,
 | 
			
		||||
+      ownerFrameId: ownerFrame ? ownerFrame.id() : undefined,
 | 
			
		||||
+    };
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
@ -2867,7 +2915,7 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
 | 
			
		||||
+    return {data};
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async dispatchKeyEvent({type, keyCode, code, key, repeat, location}) {
 | 
			
		||||
+  async dispatchKeyEvent({type, keyCode, code, key, repeat, location, text}) {
 | 
			
		||||
+    const frame = this._frameTree.mainFrame();
 | 
			
		||||
+    const tip = frame.textInputProcessor();
 | 
			
		||||
+    if (key === 'Meta' && Services.appinfo.OS !== 'Darwin')
 | 
			
		||||
@ -2881,13 +2929,21 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
 | 
			
		||||
+      repeat,
 | 
			
		||||
+      keyCode
 | 
			
		||||
+    });
 | 
			
		||||
+    const flags = 0;
 | 
			
		||||
+    if (type === 'keydown')
 | 
			
		||||
+      tip.keydown(keyEvent, flags);
 | 
			
		||||
+    else if (type === 'keyup')
 | 
			
		||||
+    if (type === 'keydown') {
 | 
			
		||||
+      if (text && text !== key) {
 | 
			
		||||
+        tip.commitCompositionWith(text, keyEvent);
 | 
			
		||||
+      } else {
 | 
			
		||||
+        const flags = 0;
 | 
			
		||||
+        tip.keydown(keyEvent, flags);
 | 
			
		||||
+      }
 | 
			
		||||
+    } else if (type === 'keyup') {
 | 
			
		||||
+      if (text)
 | 
			
		||||
+        throw new Error(`keyup does not support text option`);
 | 
			
		||||
+      const flags = 0;
 | 
			
		||||
+      tip.keyup(keyEvent, flags);
 | 
			
		||||
+    else
 | 
			
		||||
+    } else {
 | 
			
		||||
+      throw new Error(`Unknown type ${type}`);
 | 
			
		||||
+    }
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async dispatchTouchEvent({type, touchPoints, modifiers}) {
 | 
			
		||||
@ -2943,6 +2999,19 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
 | 
			
		||||
+    frame.textInputProcessor().commitCompositionWith(text);
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async crash() {
 | 
			
		||||
+    dump(`Crashing intentionally\n`);
 | 
			
		||||
+    // This is to intentionally crash the frame.
 | 
			
		||||
+    // We crash by using js-ctypes and dereferencing
 | 
			
		||||
+    // a bad pointer. The crash should happen immediately
 | 
			
		||||
+    // upon loading this frame script.
 | 
			
		||||
+    const { ctypes } = ChromeUtils.import('resource://gre/modules/ctypes.jsm');
 | 
			
		||||
+    ChromeUtils.privateNoteIntentionalCrash();
 | 
			
		||||
+    const zero = new ctypes.intptr_t(8);
 | 
			
		||||
+    const badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
 | 
			
		||||
+    badptr.contents;
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async getFullAXTree({objectId}) {
 | 
			
		||||
+    let unsafeObject = null;
 | 
			
		||||
+    if (objectId) {
 | 
			
		||||
@ -3097,10 +3166,10 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
 | 
			
		||||
+
 | 
			
		||||
diff --git a/testing/juggler/content/RuntimeAgent.js b/testing/juggler/content/RuntimeAgent.js
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..5765d5c3b1de7b9383a80435b37b034d6951d981
 | 
			
		||||
index 0000000000000000000000000000000000000000..c6568d0e98cb3405877f711a3242ab31b55ce7c1
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/testing/juggler/content/RuntimeAgent.js
 | 
			
		||||
@@ -0,0 +1,545 @@
 | 
			
		||||
@@ -0,0 +1,549 @@
 | 
			
		||||
+"use strict";
 | 
			
		||||
+// Note: this file should be loadabale with eval() into worker environment.
 | 
			
		||||
+// Avoid Components.*, ChromeUtils and global const variables.
 | 
			
		||||
@ -3445,6 +3514,10 @@ index 0000000000000000000000000000000000000000..5765d5c3b1de7b9383a80435b37b034d
 | 
			
		||||
+    return this._id;
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  auxData() {
 | 
			
		||||
+    return this._auxData;
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async evaluateScript(script, exceptionDetails = {}) {
 | 
			
		||||
+    const userInputHelper = this._domWindow ? this._domWindow.windowUtils.setHandlingUserInput(true) : null;
 | 
			
		||||
+    let {success, obj} = this._getResult(this._global.executeInGlobal(script), exceptionDetails);
 | 
			
		||||
@ -4566,7 +4639,7 @@ index 0000000000000000000000000000000000000000..5d776ab6f28ccff44ef4663e8618ad9c
 | 
			
		||||
+this.NetworkHandler = NetworkHandler;
 | 
			
		||||
diff --git a/testing/juggler/protocol/PageHandler.js b/testing/juggler/protocol/PageHandler.js
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..efb0fc1f3f7af37e101976cf8a682e09c223e59f
 | 
			
		||||
index 0000000000000000000000000000000000000000..8333a58253745298fa88f7ce17909699be43b3d4
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/testing/juggler/protocol/PageHandler.js
 | 
			
		||||
@@ -0,0 +1,266 @@
 | 
			
		||||
@ -4615,6 +4688,10 @@ index 0000000000000000000000000000000000000000..efb0fc1f3f7af37e101976cf8a682e09
 | 
			
		||||
+        this._updateModalDialogs();
 | 
			
		||||
+      }),
 | 
			
		||||
+      helper.addEventListener(this._browser, 'DOMModalDialogClosed', event => this._updateModalDialogs()),
 | 
			
		||||
+      helper.on(TargetRegistry.instance(), TargetRegistry.Events.TargetCrashed, targetId => {
 | 
			
		||||
+        if (targetId === this._chromeSession.targetId())
 | 
			
		||||
+          this._chromeSession.emitEvent('Page.crashed', {});
 | 
			
		||||
+      }),
 | 
			
		||||
+    ];
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
@ -4660,18 +4737,10 @@ index 0000000000000000000000000000000000000000..efb0fc1f3f7af37e101976cf8a682e09
 | 
			
		||||
+    return await this._contentSession.send('Page.setFileInputFiles', options);
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async setBypassCSP(options) {
 | 
			
		||||
+    return await this._contentSession.send('Page.setBypassCSP', options);
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async setEmulatedMedia(options) {
 | 
			
		||||
+    return await this._contentSession.send('Page.setEmulatedMedia', options);
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async setJavascriptEnabled(options) {
 | 
			
		||||
+    return await this._contentSession.send('Page.setJavascriptEnabled', options);
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async setCacheDisabled(options) {
 | 
			
		||||
+    return await this._contentSession.send('Page.setCacheDisabled', options);
 | 
			
		||||
+  }
 | 
			
		||||
@ -4756,6 +4825,10 @@ index 0000000000000000000000000000000000000000..efb0fc1f3f7af37e101976cf8a682e09
 | 
			
		||||
+    return await this._contentSession.send('Page.insertText', options);
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async crash(options) {
 | 
			
		||||
+    return await this._contentSession.send('Page.crash', options);
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
+  async handleDialog({dialogId, accept, promptText}) {
 | 
			
		||||
+    const dialog = this._dialogs.get(dialogId);
 | 
			
		||||
+    if (!dialog)
 | 
			
		||||
@ -4987,10 +5060,10 @@ index 0000000000000000000000000000000000000000..78b6601b91d0b7fcda61114e6846aa07
 | 
			
		||||
+this.EXPORTED_SYMBOLS = ['t', 'checkScheme'];
 | 
			
		||||
diff --git a/testing/juggler/protocol/Protocol.js b/testing/juggler/protocol/Protocol.js
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690fa7941f25
 | 
			
		||||
index 0000000000000000000000000000000000000000..6751bfaa84655952f4a51e3dd4353eb84f517fcb
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/testing/juggler/protocol/Protocol.js
 | 
			
		||||
@@ -0,0 +1,746 @@
 | 
			
		||||
@@ -0,0 +1,752 @@
 | 
			
		||||
+const {t, checkScheme} = ChromeUtils.import('chrome://juggler/content/protocol/PrimitiveTypes.js');
 | 
			
		||||
+
 | 
			
		||||
+// Protocol-specific types.
 | 
			
		||||
@ -5446,6 +5519,8 @@ index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690f
 | 
			
		||||
+  events: {
 | 
			
		||||
+    'ready': {
 | 
			
		||||
+    },
 | 
			
		||||
+    'crashed': {
 | 
			
		||||
+    },
 | 
			
		||||
+    'eventFired': {
 | 
			
		||||
+      frameId: t.String,
 | 
			
		||||
+      name: t.Enum(['load', 'DOMContentLoaded']),
 | 
			
		||||
@ -5635,7 +5710,7 @@ index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690f
 | 
			
		||||
+        executionContextId: t.String,
 | 
			
		||||
+      },
 | 
			
		||||
+      returns: {
 | 
			
		||||
+        remoteObject: runtimeTypes.RemoteObject,
 | 
			
		||||
+        remoteObject: t.Nullable(runtimeTypes.RemoteObject),
 | 
			
		||||
+      },
 | 
			
		||||
+    },
 | 
			
		||||
+    'screenshot': {
 | 
			
		||||
@ -5665,6 +5740,7 @@ index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690f
 | 
			
		||||
+        location: t.Number,
 | 
			
		||||
+        code: t.String,
 | 
			
		||||
+        repeat: t.Boolean,
 | 
			
		||||
+        text: t.Optional(t.String),
 | 
			
		||||
+      }
 | 
			
		||||
+    },
 | 
			
		||||
+    'dispatchTouchEvent': {
 | 
			
		||||
@ -5693,6 +5769,9 @@ index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690f
 | 
			
		||||
+        text: t.String,
 | 
			
		||||
+      }
 | 
			
		||||
+    },
 | 
			
		||||
+    'crash': {
 | 
			
		||||
+      params: {}
 | 
			
		||||
+    },
 | 
			
		||||
+    'handleDialog': {
 | 
			
		||||
+      params: {
 | 
			
		||||
+        dialogId: t.String,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user