Source/WebInspectorUI/ChangeLog

112016-06-27 Brian Burg <bburg@apple.com>
22
 3 Web Inspector: QuickConsole should update its selection when RuntimeManager.defaultExecutionContextIdentifier changes
 4 https://bugs.webkit.org/show_bug.cgi?id=159183
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Currently, the UI listens for state changes in the Frame tree to decide when to reset
 9 the selected execution context back to its default value. This is no good, because this
 10 should happen even if we have no UI (i.e., testing models only). The UI should simply
 11 display changes to the model rather than driving them based on other model changes.
 12
 13 Move the logic to reset the execution context into RuntimeManager. When the selected
 14 context changes, an event is fired which causes the QuickConsole to rebuild its path components.
 15
 16 * UserInterface/Controllers/RuntimeManager.js:
 17 (WebInspector.RuntimeManager):
 18 (WebInspector.RuntimeManager.prototype.set defaultExecutionContextIdentifier):
 19 Fire an event when the execution context actually changes.
 20
 21 (WebInspector.RuntimeManager.prototype._frameExecutionContextsCleared):
 22 Added. If the selected context was cleared, reset back to default.
 23
 24 * UserInterface/Models/Frame.js:
 25 (WebInspector.Frame.prototype.clearExecutionContexts):
 26 Include the contexts that were cleared so clients can match against them.
 27
 28 * UserInterface/Views/QuickConsole.js:
 29 (WebInspector.QuickConsole):
 30 Use the proper constant name. Both the old and new names evaluated to `undefined`.
 31 No need to keep track of the selected path component, it will always match the
 32 defaultExecutionContextIdentifier in RuntimeManager.
 33
 34 (WebInspector.QuickConsole.prototype.get selectedExecutionContextIdentifier):
 35 (WebInspector.QuickConsole.prototype.set selectedExecutionContextIdentifier):
 36 Forward to RuntimeManager. This name is less awkward for the UI code that manages selections.
 37
 38 (WebInspector.QuickConsole.prototype._executionContextPathComponentsToDisplay):
 39 Special-case for the main frame execution context.
 40
 41 (WebInspector.QuickConsole.prototype._framePageExecutionContextsChanged):
 42 Remove indirection.
 43
 44 (WebInspector.QuickConsole.prototype._frameExecutionContextsCleared):
 45 Fix the guard to handle undefined execution contexts in the case where it represents the main frame (undefined).
 46
 47 (WebInspector.QuickConsole.prototype._defaultExecutionContextChanged):
 48 Rebuild when the model changes.
 49
 50 (WebInspector.QuickConsole.prototype._pathComponentSelected): Simplify.
 51 (WebInspector.QuickConsole.prototype.get executionContextIdentifier):
 52 (WebInspector.QuickConsole.prototype._removeExecutionContextPathComponentForFrame):
 53 Move the fallback selection behavior into RuntimeManager.
 54
 55 (WebInspector.QuickConsole.prototype._updateExecutionContextPathComponentForFrame): Deleted.
 56 This has been dead code ever since we removed iOS 6 legacy support.
 57
 582016-06-27 Brian Burg <bburg@apple.com>
 59
360 Web Inspector: RuntimeManager should not use view object WebInspector.quickConsole
461 https://bugs.webkit.org/show_bug.cgi?id=128092
562 <rdar://problem/15966526>

Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js

@@WebInspector.RuntimeManager = class RuntimeManager extends WebInspector.Object
3131
3232 // Enable the RuntimeAgent to receive notification of execution contexts.
3333 RuntimeAgent.enable();
 34
 35 WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ExecutionContextsCleared, this._frameExecutionContextsCleared, this);
3436 }
3537
3638 // Public

@@WebInspector.RuntimeManager = class RuntimeManager extends WebInspector.Object
124126 }
125127
126128 get defaultExecutionContextIdentifier() { return this._defaultExecutionContextIdentifier; }
127  set defaultExecutionContextIdentifier(value) { this._defaultExecutionContextIdentifier = value; }
 129 set defaultExecutionContextIdentifier(value)
 130 {
 131 if (this._defaultExecutionContextIdentifier === value)
 132 return;
 133
 134 this._defaultExecutionContextIdentifier = value;
 135 this.dispatchEventToListeners(WebInspector.RuntimeManager.Event.DefaultExecutionContextChanged);
 136 }
 137
 138 // Private
 139
 140 _frameExecutionContextsCleared(event)
 141 {
 142 let contexts = event.data.contexts || [];
 143
 144 let currentContextWasDestroyed = contexts.some((context) => context.id === this._defaultExecutionContextIdentifier);
 145 if (currentContextWasDestroyed)
 146 this.defaultExecutionContextIdentifier = WebInspector.RuntimeManager.TopLevelExecutionContextIdentifier;
 147 }
128148};
129149
130150WebInspector.RuntimeManager.TopLevelExecutionContextIdentifier = undefined;
131151
132152WebInspector.RuntimeManager.Event = {
133  DidEvaluate: "runtime-manager-did-evaluate"
 153 DidEvaluate: Symbol("runtime-manager-did-evaluate"),
 154 DefaultExecutionContextChanged: Symbol("runtime-manager-default-execution-context-changed"),
134155};
135156
136157WebInspector.RuntimeManager.ConsoleObjectGroup = "console";

Source/WebInspectorUI/UserInterface/Models/Frame.js

@@WebInspector.Frame = class Frame extends WebInspector.Object
206206 clearExecutionContexts(committingProvisionalLoad)
207207 {
208208 if (this._executionContextList.contexts.length) {
 209 let contexts = this._executionContextList.contexts.slice();
209210 this._executionContextList.clear();
210  this.dispatchEventToListeners(WebInspector.Frame.Event.ExecutionContextsCleared, {committingProvisionalLoad:!!committingProvisionalLoad});
 211 this.dispatchEventToListeners(WebInspector.Frame.Event.ExecutionContextsCleared, {committingProvisionalLoad:!!committingProvisionalLoad, contexts});
211212 }
212213 }
213214

Source/WebInspectorUI/UserInterface/Views/QuickConsole.js

11/*
2  * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
 2 * Copyright (C) 2013, 2015, 2016 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@WebInspector.QuickConsole = class QuickConsole extends WebInspector.View
3131
3232 this._toggleOrFocusKeyboardShortcut = new WebInspector.KeyboardShortcut(null, WebInspector.KeyboardShortcut.Key.Escape, this._toggleOrFocus.bind(this));
3333
34  var mainFrameExecutionContext = new WebInspector.ExecutionContext(WebInspector.QuickConsole.MainFrameContextExecutionIdentifier, WebInspector.UIString("Main Frame"), true, null);
 34 let mainFrameExecutionContext = new WebInspector.ExecutionContext(WebInspector.RuntimeManager.TopLevelContextExecutionIdentifier, WebInspector.UIString("Main Frame"), true, null);
3535 this._mainFrameExecutionContextPathComponent = this._createExecutionContextPathComponent(mainFrameExecutionContext.name, mainFrameExecutionContext.identifier);
36  this._selectedExecutionContextPathComponent = this._mainFrameExecutionContextPathComponent;
3736
3837 this._otherExecutionContextPathComponents = [];
3938 this._frameIdentifierToExecutionContextPathComponentMap = {};

@@WebInspector.QuickConsole = class QuickConsole extends WebInspector.View
7069 WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ExecutionContextsCleared, this._frameExecutionContextsCleared, this);
7170
7271 WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._debuggerActiveCallFrameDidChange, this);
 72
 73 WebInspector.runtimeManager.addEventListener(WebInspector.RuntimeManager.Event.DefaultExecutionContextChanged, this._defaultExecutionContextChanged, this);
7374 }
7475
7576 // Public

@@WebInspector.QuickConsole = class QuickConsole extends WebInspector.View
7980 return this._navigationBar;
8081 }
8182
82  get executionContextIdentifier()
 83 get selectedExecutionContextIdentifier()
8384 {
84  return this._selectedExecutionContextPathComponent._executionContextIdentifier;
 85 return WebInspector.runtimeManager.defaultExecutionContextIdentifier;
 86 }
 87
 88 set selectedExecutionContextIdentifier(value)
 89 {
 90 if (value === this.selectedExecutionContextIdentifier)
 91 return;
 92
 93 WebInspector.runtimeManager.defaultExecutionContextIdentifier = value;
8594 }
8695
8796 consoleLogVisibilityChanged(visible)

@@WebInspector.QuickConsole = class QuickConsole extends WebInspector.View
124133 if (!this._otherExecutionContextPathComponents.length)
125134 return [];
126135
127  return [this._selectedExecutionContextPathComponent];
 136 if (this.selectedExecutionContextIdentifier === this._mainFrameExecutionContextPathComponent._executionContextIdentifier)
 137 return [this._mainFrameExecutionContextPathComponent];
 138
 139 return this._otherExecutionContextPathComponents.filter((component) => component._executionContextIdentifier === this.selectedExecutionContextIdentifier);
128140 }
129141
130142 _rebuildExecutionContextPathComponents()

@@WebInspector.QuickConsole = class QuickConsole extends WebInspector.View
147159 var newExecutionContextPathComponent = this._insertExecutionContextPathComponentForFrame(frame, shouldAutomaticallySelect);
148160
149161 if (shouldAutomaticallySelect) {
150  delete this._restoreSelectedExecutionContextForFrame;
151  this._selectedExecutionContextPathComponent = newExecutionContextPathComponent;
152  WebInspector.runtimeManager.defaultExecutionContextIdentifier = this.executionContextIdentifier;
153  this._rebuildExecutionContextPathComponents();
 162 this._restoreSelectedExecutionContextForFrame = null;
 163 this.selectedExecutionContextIdentifier = newExecutionContextPathComponent._executionContextIdentifier;
154164 }
155165 }
156166
157167 _frameExecutionContextsCleared(event)
158168 {
159  var frame = event.target;
 169 let frame = event.target;
160170
161171 // If this frame is navigating and it is selected in the UI we want to reselect its new item after navigation.
162172 if (event.data.committingProvisionalLoad && !this._restoreSelectedExecutionContextForFrame) {
163  var executionContextPathComponent = this._frameIdentifierToExecutionContextPathComponentMap[frame.id];
164  if (this._selectedExecutionContextPathComponent === executionContextPathComponent) {
 173 let executionContextPathComponent = this._frameIdentifierToExecutionContextPathComponentMap[frame.id];
 174 if (executionContextPathComponent && executionContextPathComponent._executionContextIdentifier === this.selectedExecutionContextIdentifier) {
165175 this._restoreSelectedExecutionContextForFrame = frame;
166176 // As a fail safe, if the frame never gets an execution context, clear the restore value.
167  setTimeout(function() { delete this._restoreSelectedExecutionContextForFrame; }.bind(this), 10);
 177 setTimeout(() => { this._restoreSelectedExecutionContextForFrame = false; }, 10);
168178 }
169179 }
170180
171181 this._removeExecutionContextPathComponentForFrame(frame);
172182 }
173183
 184 _defaultExecutionContextChanged(event)
 185 {
 186 this._rebuildExecutionContextPathComponents();
 187 }
 188
174189 _createExecutionContextPathComponent(name, identifier)
175190 {
176191 var pathComponent = new WebInspector.HierarchicalPathComponent(name, "execution-context", identifier, true, true);

@@WebInspector.QuickConsole = class QuickConsole extends WebInspector.View
261276 if (next)
262277 next.previousSibling = prev;
263278
264  if (this._selectedExecutionContextPathComponent === executionContextPathComponent) {
265  this._selectedExecutionContextPathComponent = this._mainFrameExecutionContextPathComponent;
266  WebInspector.runtimeManager.defaultExecutionContextIdentifier = this.executionContextIdentifier;
267  }
268 
269279 this._otherExecutionContextPathComponents.remove(executionContextPathComponent, true);
270280 delete this._frameIdentifierToExecutionContextPathComponentMap[frame.id];
271281

@@WebInspector.QuickConsole = class QuickConsole extends WebInspector.View
273283 this._rebuildExecutionContextPathComponents();
274284 }
275285
276  _updateExecutionContextPathComponentForFrame(frame)
277  {
278  if (frame.isMainFrame())
279  return;
280 
281  var executionContextPathComponent = this._frameIdentifierToExecutionContextPathComponentMap[frame.id];
282  if (!executionContextPathComponent)
283  return;
284 
285  var wasSelected = this._selectedExecutionContextPathComponent === executionContextPathComponent;
286 
287  this._removeExecutionContextPathComponentForFrame(frame, true);
288  var newExecutionContextPathComponent = this._insertExecutionContextPathComponentForFrame(frame, true);
289 
290  if (wasSelected) {
291  this._selectedExecutionContextPathComponent = newExecutionContextPathComponent;
292  WebInspector.runtimeManager.defaultExecutionContextIdentifier = this.executionContextIdentifier;
293  }
294 
295  this._rebuildExecutionContextPathComponents();
296  }
297 
298286 _pathComponentSelected(event)
299287 {
300  if (event.data.pathComponent === this._selectedExecutionContextPathComponent)
301  return;
302 
303  this._selectedExecutionContextPathComponent = event.data.pathComponent;
304  WebInspector.runtimeManager.defaultExecutionContextIdentifier = this.executionContextIdentifier;
305 
306  this._rebuildExecutionContextPathComponents();
 288 this.selectedExecutionContextIdentifier = event.data.pathComponent._executionContextIdentifier;
307289 }
308290
309291 _pathComponentClicked(event)

LayoutTests/ChangeLog

112016-06-27 Brian Burg <bburg@apple.com>
22
 3 Web Inspector: QuickConsole should update its selection when RuntimeManager.defaultExecutionContextIdentifier changes
 4 https://bugs.webkit.org/show_bug.cgi?id=159183
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Add a new test case for reverting to the top-level execution context when the selected context is destroyed.
 9
 10 * inspector/runtime/change-execution-context-identifier-expected.txt:
 11 * inspector/runtime/change-execution-context-identifier.html:
 12
 132016-06-27 Brian Burg <bburg@apple.com>
 14
315 Web Inspector: RuntimeManager should not use view object WebInspector.quickConsole
416 https://bugs.webkit.org/show_bug.cgi?id=128092
517 <rdar://problem/15966526>

LayoutTests/inspector/runtime/change-execution-context-identifier-expected.txt

1 
21Test that RuntimeManager.evaluateInInspectedWindow respects the selected execution context.
32
43

@@PASS: The passphrase should match the phrase defined in the subframe.
1918Passphrase in selected frame: coldwater
2019PASS: The passphrase should match the phrase defined in the main frame.
2120
 21-- Running test case: ScriptExecutionContextRemoveSubframe
 22PASS: The test page should only have one sub-frame.
 23PASS: The test page should now have no sub-frames.
 24PASS: When a selected non-top-level execution context is removed, the default execution context should revert to the top-level context.
 25

LayoutTests/inspector/runtime/change-execution-context-identifier.html

@@function test()
3636 description: "Test that evaluateInInspectedWindow works when defaultExecutionContextIdentifier is a subframe context.",
3737 test: (resolve, reject) => {
3838 let mainFrame = WebInspector.frameResourceManager.mainFrame;
39  let subframes = WebInspector.frameResourceManager.frames.filter((frame) => frame != mainFrame);
 39 let subframes = WebInspector.frameResourceManager.frames.filter((frame) => frame !== mainFrame);
4040 InspectorTest.expectThat(subframes.length === 1, "The test page should only have one sub-frame.");
4141
4242 WebInspector.runtimeManager.defaultExecutionContextIdentifier = subframes[0].pageExecutionContext.id;

@@function test()
6363 }
6464 });
6565
 66 suite.addTestCase({
 67 name: "ScriptExecutionContextRemoveSubframe",
 68 description: "Test that evaluateInInspectedWindow works when the defaultExecutionContextIdentifier is destroyed and reverts to the top-level context.",
 69 test: (resolve, reject) => {
 70 let mainFrame = WebInspector.frameResourceManager.mainFrame;
 71 let subframes = WebInspector.frameResourceManager.frames.filter((frame) => frame !== mainFrame);
 72 InspectorTest.expectThat(subframes.length === 1, "The test page should only have one sub-frame.");
 73
 74 // Set the execution context to the subframe so we can switch away from it when the frame is detached.
 75 WebInspector.runtimeManager.defaultExecutionContextIdentifier = subframes[0].pageExecutionContext.id;
 76
 77 // Force-override the contextId, otherwise we won't be able to access the iframe's DOM element when evaluating in the iframe execution context.
 78 let expression = `document.getElementById("subframe").remove();`;
 79 let objectGroup = "test";
 80 let contextId = WebInspector.RuntimeManager.TopLevelExecutionContextIdentifier;
 81 RuntimeAgent.evaluate.invoke({expression, objectGroup, contextId}, () => {
 82 InspectorTest.expectThat(WebInspector.frameResourceManager.frames.length === 1, "The test page should now have no sub-frames.");
 83 InspectorTest.expectThat(WebInspector.runtimeManager.defaultExecutionContextIdentifier === WebInspector.RuntimeManager.TopLevelExecutionContextIdentifier, "When a selected non-top-level execution context is removed, the default execution context should revert to the top-level context.");
 84 resolve();
 85 });
 86 }
 87 });
 88
6689 suite.runTestCasesAndFinish();
6790}
6891</script>
6992</head>
7093<body>
71 <iframe src="resources/change-execution-context-identifier-subframe.html" onload="runTest()"></iframe>
 94<iframe id="subframe" src="resources/change-execution-context-identifier-subframe.html" onload="runTest()"></iframe>
7295<p>Test that RuntimeManager.evaluateInInspectedWindow respects the selected execution context.</p>
7396</body>
7497</html>