Closed Bug 1084525 Opened 11 years ago Closed 10 years ago

Implement remote debugging protocol support for observing promises and their fulfillments/rejections

Categories

(DevTools :: Debugger, defect)

x86
macOS
defect
Not set
normal

Tracking

(firefox41 fixed)

RESOLVED FIXED
Firefox 41
Tracking Status
firefox41 --- fixed

People

(Reporter: fitzgen, Assigned: gl)

References

(Blocks 1 open bug)

Details

Attachments

(13 files, 30 obsolete files)

6.55 KB, patch
Details | Diff | Splinter Review
4.69 KB, patch
Details | Diff | Splinter Review
6.06 KB, patch
Details | Diff | Splinter Review
9.68 KB, patch
Details | Diff | Splinter Review
8.68 KB, patch
fitzgen
: review+
Details | Diff | Splinter Review
6.94 KB, patch
Details | Diff | Splinter Review
8.32 KB, patch
Details | Diff | Splinter Review
7.71 KB, patch
Details | Diff | Splinter Review
9.14 KB, patch
Details | Diff | Splinter Review
12.61 KB, patch
Details | Diff | Splinter Review
4.36 KB, patch
Details | Diff | Splinter Review
2.07 KB, patch
Details | Diff | Splinter Review
4.18 KB, patch
Details | Diff | Splinter Review
Warning: a bunch of brain dump going on here. Types of things we should support over the RDP, and how we can go about it: a) When the frontend first starts observing promises, we can find all live promises in the debuggees via `Debugger.prototype.findObjects({ class: "Promise" })` to populate the frontend's display. b) We can use the Debugger.prototype.onNewPromise hook to notify the frontend of new promise allocations, so it can keep its list of promises up to date. c) We can use the Debuger.prototype.onPromiseSettled hook to notify the frontend of state changes, so it can keep each promise it is displaying up to date. d) To get the various bits of internal data out of promises, we have the PromiseDebugging webidl interface. This requires operating on actual Promise instances, not Debugger.Object wrappers. Rather than unwrapping D.Os everywhere, I think we should monkey patch the `Debugger.Object.prototype` object with a corresponding method for each of the methods on PromiseDebugging that does the unwrapping, gets the data and returns it. This way we can encapsulate the unwrapping and the debugger logic doesn't ever have to deal with unwrapped debuggee objects directly. We should use those above methods to extend the ObjectActor's form + request types as it makes sense to expose data about individual promises over the RDP. This might happen in another bug. Originally, the plan was to do this part in bug 1033153, but it seems taken over as a meta bug for general "private data that can be exposed as PromiseDebugging methods" type bugs. Maybe that's still the best place to do it. Still need to think about the exact implementation of packet forms, notifications, and request/response interactions. I'm leaning towards a "live list" (like the root actor's tab list), where you can get the whole list up front and then once you've done that you can get a single notification when that the list has changed and if you want the new list after that, you just re-request the whole list (or maybe the subset of the list that is new?). This avoids too much RDP traffic for every single change, and doesn't require any synchronization work by the client. I think sending a packet per promise (like we do with sources, for example) could become too much RDP traffic. Maybe we can do the same thing for settlements? A single notification when at least one promise we are observing has settled, and then you can request all the promise states at once or maybe just the states of promises that have settled since last time you requested these states. The thing is, we will definitely need a per-promise state request type just to show promise state for promises that come in scope as you step in the debugger. Maybe we should only do that latter, per-promise state request option, if we have to implement it anyways. Why duplicate work?
Assignee: nobody → gabriel.luong
List of modifications: - Updated the unit test to the new style - I renamed and abstracted startTestDebuggerServer from startTestPromiseServer since we can easily reuse this function in other tests
Attachment #8611440 - Flags: review?(nfitzgerald)
Comment on attachment 8611440 [details] [diff] [review] Part 1: Create initial PromiseActor skeleton Review of attachment 8611440 [details] [diff] [review]: ----------------------------------------------------------------- v nice
Attachment #8611440 - Flags: review?(nfitzgerald) → review+
Comment on attachment 8611457 [details] [diff] [review] Part 2: Refactor expectState from memory-bridge.js to common.js Review of attachment 8611457 [details] [diff] [review]: ----------------------------------------------------------------- Yup.
Attachment #8611457 - Flags: review?(nfitzgerald) → review+
Attachment #8611499 - Flags: review?(nfitzgerald)
Comment on attachment 8611499 [details] [diff] [review] Part 3: Add attach and detach methods to PromiseActor Review of attachment 8611499 [details] [diff] [review]: ----------------------------------------------------------------- LGTM
Attachment #8611499 - Flags: review?(nfitzgerald) → review+
Depends on: 1169064
Attached patch 1084525-part-4.patch (obsolete) — Splinter Review
Status: NEW → ASSIGNED
Attachment #8613074 - Attachment is obsolete: true
Attachment #8613177 - Flags: review?(nfitzgerald)
Attachment #8613177 - Flags: review?(nfitzgerald)
Added docs
Attachment #8613177 - Attachment is obsolete: true
Attachment #8613178 - Flags: review?(nfitzgerald)
Attachment #8613652 - Attachment is obsolete: true
Attachment #8613720 - Attachment is obsolete: true
Comment on attachment 8613733 [details] [diff] [review] Part 5: Add onNewPromise event handler to Promise Actor WIP2 Review of attachment 8613733 [details] [diff] [review]: ----------------------------------------------------------------- ::: toolkit/devtools/server/actors/promise.js @@ +26,5 @@ > > + events: { > + // Event emitted for new promises allocated in debuggee and bufferred so > + // we send them in a batch. > + "new-promise": { Nit: Since we send an array of new promises, we should probably name the event "new-promises" rather than "new-promise". @@ +183,5 @@ > + > + if (needsScheduling) { > + DevToolsUtils.executeSoon(() => { > + events.emit(this, eventName, array); > + array = []; We need to use the splice trick here, or else we will leak the very first array of promises that are still attached to the actor at `this._newPromises` because this line only rebinds the local `array` binding and not the reference from `this`. Alternatively, pass in a property name and replace this line with: this[arrayPropertyName] = []; And change the other references to `array` in a similar way throughout the body of this method.
Comment on attachment 8613178 [details] [diff] [review] Part 4: Add listPromises method to Promise Actor [1.0] Review of attachment 8613178 [details] [diff] [review]: ----------------------------------------------------------------- Great! Aside: let's rename this file to promises.js and the actor to PromisesActor. PromiseActor implies an actor for a single promise / per promise, when the reality is that we just reuse ObjectActor for each promise. This is an actor for all debuggee promises -- plural -- and the name should reflect that. ::: toolkit/devtools/server/actors/promise.js @@ +118,5 @@ > + createValueGrip(v, this._navigationLifetimePool, this.objectGrip), > + sources: () => DevToolsUtils.reportException("PromiseActor", > + Error("sources not yet implemented")), > + createEnvironmentActor: () => DevToolsUtils.reportException( > + "PromiseActor", Error("sources not yet implemented")) s/sources/createEnvironmentActor/
Attachment #8613178 - Flags: review?(nfitzgerald) → review+
Attachment #8613733 - Attachment is obsolete: true
Attachment #8613795 - Flags: review?(nfitzgerald)
Attachment #8611440 - Attachment is obsolete: true
Attachment #8613877 - Flags: review+
Rebased and renamed to PromisesActor
Attachment #8611499 - Attachment is obsolete: true
Attachment #8613879 - Flags: review+
Attachment #8613878 - Flags: review+
Rebased and renamed to PromisesActor. Addressed feedback.
Attachment #8613178 - Attachment is obsolete: true
Attachment #8613880 - Flags: review+
Attachment #8613795 - Attachment is obsolete: true
Attachment #8613795 - Flags: review?(nfitzgerald)
Attachment #8613882 - Flags: review?(nfitzgerald)
Comment on attachment 8613882 [details] [diff] [review] Part 5: Add onNewPromise event handler to PromisesActor [2.0] Review of attachment 8613882 [details] [diff] [review]: ----------------------------------------------------------------- Nice
Attachment #8613882 - Flags: review?(nfitzgerald) → review+
Attachment #8613653 - Attachment is obsolete: true
Attachment #8614186 - Flags: review?(nfitzgerald)
Comment on attachment 8614186 [details] [diff] [review] Part 6: Add onPromiseSettled event handler to Promise Actor [1.0] Review of attachment 8614186 [details] [diff] [review]: ----------------------------------------------------------------- Great! One nit and one requested change below. ::: toolkit/devtools/server/actors/promises.js @@ +30,5 @@ > "new-promises": { > type: "new-promises", > data: Arg(0, "array:ObjectActor"), > + }, > + // Event emitted for promise settlements Nit: missing a period here. ::: toolkit/devtools/server/tests/unit/test_promises_actor_onpromisesettled.js @@ +72,5 @@ > + p.promiseState.value === resolution) { > + resolve(true); > + } else if (p.promiseState.state === "rejected" && > + p.promiseState.reason === resolution) { > + resolve(true); Instead of always resolving if we find a fulfillment or rejection with the expected value, let's explicitly pass in a parameter specifying whether we expect it to be fulfilled or rejected. This makes the test just a little tighter.
Attachment #8614186 - Flags: review?(nfitzgerald) → review+
Attachment #8613877 - Flags: checkin+
Attachment #8613878 - Flags: checkin+
Attachment #8613879 - Flags: checkin+
Attachment #8613880 - Flags: checkin+
Attachment #8613882 - Flags: checkin+
Attachment #8614208 - Flags: checkin+
Attachment #8614421 - Flags: review?(nfitzgerald)
Attachment #8614422 - Flags: review?(nfitzgerald)
Comment on attachment 8614421 [details] [diff] [review] Part 7: Expose Promise life time in object grip Review of attachment 8614421 [details] [diff] [review]: ----------------------------------------------------------------- r=me with quick test asserting that p = new Promise expected = Date.now() onNewPromise(p) => { assert p.creationTime about equal to expected (say within 2 ms) }
Attachment #8614421 - Flags: review?(nfitzgerald) → review+
Comment on attachment 8614422 [details] [diff] [review] Part 8: Expose Promise time to settle in object grip Review of attachment 8614422 [details] [diff] [review]: ----------------------------------------------------------------- Would like to do a quick re-review when you have tests for: * Promise.resolve() and Promise.reject() should both have a time-to-settle of 0 * return new Promise(resolve => setTimeout(resolve, 100)) should have time-to-settle of about 100 ms * A promise that is not settled should not have a time-to-settle
Attachment #8614422 - Flags: review?(nfitzgerald)
(In reply to Nick Fitzgerald [:fitzgen][:nf] from comment #29) > Comment on attachment 8614421 [details] [diff] [review] > Part 7: Expose Promise life time in object grip > > Review of attachment 8614421 [details] [diff] [review]: > ----------------------------------------------------------------- > > r=me with quick test asserting that > > p = new Promise > expected = Date.now() > > onNewPromise(p) => { > assert p.creationTime about equal to expected (say within 2 ms) > } Or, even better: start = Date.now() p = new Promise end = Date.now(); onNewPromise: assert that start <= p.creationTimestamp <= end
Attachment #8614950 - Flags: review?(nfitzgerald)
Attachment #8614950 - Attachment is obsolete: true
Attachment #8614950 - Flags: review?(nfitzgerald)
Attachment #8614966 - Flags: review?(nfitzgerald)
Comment on attachment 8614966 [details] [diff] [review] Part 9: Implement getDependentPromises method in ObjectClient [1.0] Review of attachment 8614966 [details] [diff] [review]: ----------------------------------------------------------------- Nice work! ::: toolkit/devtools/client/dbg-client.jsm @@ +2426,5 @@ > + }, { > + before: function(aPacket) { > + if (this._grip.class !== "Promise") { > + throw new Error("getDependentPromises is only valid for promise " + > + "grips."); You can use template (backtick) strings for multiline strings. ::: toolkit/devtools/server/actors/object.js @@ +528,5 @@ > + onDependentPromises: function() { > + if (this.obj.class != "Promise") { > + return { error: "objectNotPromise", > + message: "'dependentPromises' request is only valid for " + > + "object grips with a 'Promise' class." }; ditto re: multiline strings
Attachment #8614966 - Flags: review?(nfitzgerald) → review+
Comment on attachment 8614966 [details] [diff] [review] Part 9: Implement getDependentPromises method in ObjectClient [1.0] Review of attachment 8614966 [details] [diff] [review]: ----------------------------------------------------------------- ::: toolkit/devtools/client/dbg-client.jsm @@ +2426,5 @@ > + }, { > + before: function(aPacket) { > + if (this._grip.class !== "Promise") { > + throw new Error("getDependentPromises is only valid for promise " + > + "grips."); Template strings would put "grips" on a new line and we don't actually want multiple lines here.
(In reply to Gabriel Luong [:gl] from comment #36) > Comment on attachment 8614966 [details] [diff] [review] > Part 9: Implement getDependentPromises method in ObjectClient [1.0] > > Review of attachment 8614966 [details] [diff] [review]: > ----------------------------------------------------------------- > > ::: toolkit/devtools/client/dbg-client.jsm > @@ +2426,5 @@ > > + }, { > > + before: function(aPacket) { > > + if (this._grip.class !== "Promise") { > > + throw new Error("getDependentPromises is only valid for promise " + > > + "grips."); > > Template strings would put "grips" on a new line and we don't actually want > multiple lines here. Ah, you are of course correct.
Attachment #8615644 - Attachment is obsolete: true
Attachment #8616099 - Flags: feedback?(nfitzgerald)
Comment on attachment 8616099 [details] [diff] [review] Part 10: Implement getAllocationStack method in ObjectClient WIP Review of attachment 8616099 [details] [diff] [review]: ----------------------------------------------------------------- Extra f? jlongster because he is the other person who really knows what's going on with sources these days, especially when used outside of the debugger. I think we need a way to ensure that TabSources can be populated on demand, and doesn't rely on the ThreadActor. The more I think about it, the more I think we might want to organize a vidyo meeting (and possibly postpone source mapping for now). ::: toolkit/devtools/server/actors/object.js @@ +543,5 @@ > + > + /** > + * Handle a protocol request to get the allocation stack of a promise. > + */ > + onAllocationStack: Task.async(function*() { It used to be that we couldn't use Task.jsm in actors used by the debugger, and I'm not sure if that restriction has been lifted, or if it still even applies anymore now that we moved the ObjectActor out to its own module. I think the issue might have been that Task.jsm uses Promise.jsm (and not native DOM Promises) and Promise.jsm is not worker-compatible, which the ThreadActor and related actors must be. Additional f? ejpbruel for more info / guidance here. @@ +566,5 @@ > + }), > + > + _getSourceOriginalLocation: function(stack) { > + return this.hooks.sources().getOriginalLocation(new GeneratedLocation( > + this.hooks.sources().createNonSourceMappedActor(stack.source), createNonSourceMappedActor takes a Debugger.Source instance, not a source url/filename string which is what SavedFrame.prototype.source gives. I think the best thing we can do now is hope that the source actor for the generated source has already been created and do TabSources.prototype.getSourceActorByURL. Note that because we don't have a Debugger.Source (which has the full source text / etc needed to make a SourceActor) we can't create the actual SourceActor ourselves. I think that fixing this properly would involve some platform work, and perhaps some TabSources refactoring as well. I don't think we want to go too far down this rabbit hole here. ::: toolkit/devtools/server/tests/unit/test_promises_client_getallocationstack.js @@ +62,5 @@ > + for (let p of promises) { > + if (p.preview.ownProperties.name && > + p.preview.ownProperties.name.value === "p") { > + grip = p; > + resolve(); Why not `resolve(p)` and then do `let grip = yield onNewPromise;` below? I think explicitly returning values is much more clear and less error prone than mutating shared variables.
Attachment #8616099 - Flags: feedback?(nfitzgerald)
Attachment #8616099 - Flags: feedback?(jlong)
Attachment #8616099 - Flags: feedback?(ejpbruel)
Attachment #8616099 - Flags: feedback+
See Also: → 1172116
Comment on attachment 8616099 [details] [diff] [review] Part 10: Implement getAllocationStack method in ObjectClient WIP Review of attachment 8616099 [details] [diff] [review]: ----------------------------------------------------------------- ::: toolkit/devtools/client/dbg-client.jsm @@ +2435,5 @@ > + > + /** > + * Request the stack to the promise's allocation point. > + */ > + getAllocationStack: DebuggerClient.requester({ If this is only available for promises, can we rename this to make that more explicit? Or do we hope in the future to be able to call this for any object? ::: toolkit/devtools/server/actors/object.js @@ +566,5 @@ > + }), > + > + _getSourceOriginalLocation: function(stack) { > + return this.hooks.sources().getOriginalLocation(new GeneratedLocation( > + this.hooks.sources().createNonSourceMappedActor(stack.source), What is `stack.source` here, a URL? What happens for eval sources? We really do need to improve how sources are interacting with everything. What you theoretically should be doing is calling `getSourceActorByURL`. I want to populate `TabSources` on demand when the toolbox is opened anyway, we need it far too often to try to make it lazy somehow. We're going to talk about it more at Whistler. Until then I would recommend just not supporting sourcemaps.
Attachment #8616099 - Flags: feedback?(jlong)
Comment on attachment 8616099 [details] [diff] [review] Part 10: Implement getAllocationStack method in ObjectClient WIP The problem with using Task.jsm in script actors is that we cannot use JSMs in workers (because Components is not available, neither is Cu.import). It should be possible to work around that by converting Task.jsm to a CommonJS module, and in fact, we have done something similar for Promise.jsm (converting Promise-backend.js into a CommonJS module). Until we do, however, Task.jsm is off-limit for the script actors. In case you decide to port Task.jsm to workers, another thing to watch out for is that native DOM promises are not aware of nested event loops created by the debugger, so they will not behave like expected if you use them in the debugger on a worker thread. I've refactored Promise.jsm so that it *is* aware of nested event loops in workers, so you can use that instead.
Attachment #8616099 - Flags: feedback?(ejpbruel) → feedback-
I seem to be getting the same date timestamp for: start = Date.now() p = new Promise() end = Date.now() I tried new Date() and I would still get the exact same timestamp for start and end. Looking for feedback on what to do.
Attachment #8614421 - Attachment is obsolete: true
Attachment #8616777 - Flags: feedback?(nfitzgerald)
Comment on attachment 8616777 [details] [diff] [review] Part 7: Expose Promise life time in object grip [1.0] Review of attachment 8616777 [details] [diff] [review]: ----------------------------------------------------------------- It's ok to have start and end be the same number of ms, we are just using them as an inclusive bound: `start <= allocTimestamp <= end`. Note that we are using `<=`, and not `<`. Rather than taking `start` and `end` timestamps inside the functions passed into `testPromiseCreationTimestamp` and then sticking them on the promise as properties, I think it would be cleaner if `testPromiseCreationTimestamp` took them itself. This way we wouldn't be repeating that in both functions passed in, nor dealing with funky grip properties. function* testPromiseCreationTimestamp(client, form, makePromise) { ... let start = Date.now(); let promise = makePromise(); let end = Date.now(); ... ok(start <= creationTimestamp); ok(creationTimestamp <= end); ... }
Attachment #8616777 - Flags: feedback?(nfitzgerald)
(In reply to James Long (:jlongster) from comment #42) > Comment on attachment 8616099 [details] [diff] [review] > Part 10: Implement getAllocationStack method in ObjectClient WIP > > Review of attachment 8616099 [details] [diff] [review]: > ----------------------------------------------------------------- > > ::: toolkit/devtools/client/dbg-client.jsm > @@ +2435,5 @@ > > + > > + /** > > + * Request the stack to the promise's allocation point. > > + */ > > + getAllocationStack: DebuggerClient.requester({ > > If this is only available for promises, can we rename this to make that more > explicit? Or do we hope in the future to be able to call this for any object?\ We could totally (and should) check Debugger.Object.prototype.allocationSite if the object is not a promise. > ::: toolkit/devtools/server/actors/object.js > @@ +566,5 @@ > > + }), > > + > > + _getSourceOriginalLocation: function(stack) { > > + return this.hooks.sources().getOriginalLocation(new GeneratedLocation( > > + this.hooks.sources().createNonSourceMappedActor(stack.source), > > What is `stack.source` here, a URL? What happens for eval sources? Stack is a SavedFrame stack, so source is the filename/URL string. For eval sources, that means it is something like `foo.js:234 > eval`. > We really do need to improve how sources are interacting with everything. > What you theoretically should be doing is calling `getSourceActorByURL`. I > want to populate `TabSources` on demand when the toolbox is opened anyway, > we need it far too often to try to make it lazy somehow. > > We're going to talk about it more at Whistler. Until then I would recommend > just not supporting sourcemaps. I think the problem isn't actually source maps, the more that I think about it. We only have a URL and no D.Source, so even non-source-mapped sources are a problem if the TabSources isn't populated. Gabriel, we're going to have to work around this by manually ensuring that the TabSources is populated while we are in the attached state ourselves. That means doing something like `dbg.findScripts().forEach(s => populateTabSources(s.source))` and adding a `dbg.onNewScript = s => populateTabSources(s.source)` hook on attach. Then on detach, removing the `onNewScript` hook. I think the `populateTabSources` hand waving should be a call to `TabSources.prototype.createSourceActors`, but I'm not 100% sure. I'll let you verify that. After the source actors have been created, then you can just go ahead and get the original, potentially-source-mapped locations no problem.
(In reply to Eddy Bruel [:ejpbruel] from comment #43) Gabriel, in light of the information that Eddy provided, I recommend avoiding Task.jsm for now and rewriting with raw promises. Let's limit the number of rabbit holes we have to go down.
Added test for: * Promise.resolve() and Promise.reject() should both have a time-to-settle of 0 * return new Promise(resolve => setTimeout(resolve, 100)) should have time-to-settle of about 100 ms * A promise that is not settled should not have a time-to-settle
Attachment #8614422 - Attachment is obsolete: true
Attachment #8616837 - Flags: review?(nfitzgerald)
Comment on attachment 8616837 [details] [diff] [review] Part 8: Expose Promise time to settle in object grip [1.0] Review of attachment 8616837 [details] [diff] [review]: ----------------------------------------------------------------- Looks great! ::: toolkit/devtools/server/actors/object.js @@ +146,5 @@ > PromiseDebugging.getPromiseLifetime(rawPromise); > > + try { > + promiseState.timeToSettle = PromiseDebugging.getTimeToSettle(rawPromise); > + } catch(e) {} Should have mentioned this before (sorry), but we should comment why we are swallowing errors here. Something like "If the promise is not settled, getTimeToSettle will throw an error, and we avoid adding the timeToSettle property."
Attachment #8616837 - Flags: review?(nfitzgerald) → review+
Attachment #8616777 - Attachment is obsolete: true
Attachment #8616957 - Flags: review?(nfitzgerald)
Comment on attachment 8616957 [details] [diff] [review] Part 7: Expose Promise life time in object grip [2.0] Review of attachment 8616957 [details] [diff] [review]: ----------------------------------------------------------------- ::: toolkit/devtools/server/tests/unit/test_promises_object_creationtimestamp.js @@ +59,5 @@ > + ok(grip, "Found our new promise."); > + > + let creationTimestamp = grip.promiseState.creationTimestamp; > + > + ok(start <= creationTimestamp <= end, "Expect promise creation timestamp " + Unfortunately, you have to split this into two comparisons. Unlike python, JS doesn't desugar multiple comparisons "properly"; it's just left associative. Take this for example: js> 3 > 2 > 1 false This is because it is parsed as `(3 > 2) > 1`, which is equivalent to `true > 1`, which is equivalent to `1 > 1`, which is false. Hooray for weakly typed languages! Split it out into `start <= creationTimestamp && creationTimestamp <= end`.
Attachment #8616957 - Flags: review?(nfitzgerald) → review+
I split the checks to `start - 1 <= creationTimestamp && creationTimestamp <= end + 1` to avoid an intermittent failure with Date.now() getting an earlier end time. Doing various Math round/ceil/floor did not help either and should be avoided.
Attachment #8616957 - Attachment is obsolete: true
Attachment #8616987 - Flags: review+
Added comment on why we catch for PromiseDebugging.getTimeToSettle
Attachment #8616837 - Attachment is obsolete: true
Attachment #8616989 - Flags: review+
Switched to flooring the time to settle instead of rounding since we expect it to be 0. https://treeherder.mozilla.org/#/jobs?repo=try&revision=37933f187e22
Attachment #8616989 - Attachment is obsolete: true
Attachment #8617603 - Flags: review+
Attachment #8616987 - Flags: checkin+
Attachment #8616993 - Flags: checkin+
Attachment #8617603 - Flags: checkin+
Attachment #8616099 - Attachment is obsolete: true
Attachment #8621224 - Flags: feedback?(nfitzgerald)
Attachment #8621224 - Flags: feedback?(nfitzgerald)
test_promises_Actor_onpromisesettled.js was removed in bug 1164564, but only the assertion that the settlement time is equal to 0 should've been removed. We found that check that to be racy, but test_promises_object_timetosettle-02.js should be sufficient in checking the approximate time to settle.
Attachment #8621224 - Attachment is obsolete: true
Attachment #8623104 - Flags: review?(nfitzgerald)
Attachment #8623107 - Flags: review?(nfitzgerald)
Comment on attachment 8623104 [details] [diff] [review] Part 10: Implement getAllocationStack method in ObjectClient [1.0] Review of attachment 8623104 [details] [diff] [review]: ----------------------------------------------------------------- Great!
Attachment #8623104 - Flags: review?(nfitzgerald) → review+
Comment on attachment 8623106 [details] [diff] [review] Part 11: Add test for asserting the list of Promise objects returned from the PromiseActor onPromiseSettled event handler [1.0] Review of attachment 8623106 [details] [diff] [review]: ----------------------------------------------------------------- Mmmmmm love me some tests
Attachment #8623106 - Flags: review?(nfitzgerald) → review+
Attachment #8623107 - Flags: review?(nfitzgerald) → review+
Depends on: 1157456
Added a try catch in the case getSourceByURL fails. This error was happening in the test in the try runs (See https://treeherder.mozilla.org/logviewer.html#?job_id=8664044&repo=try): 2 INFO Console message: [JavaScript Error: "error occurred while processing 'allocationStack: Error: getSourceByURL: could not find source for chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js Stack: TabSources.prototype.getSourceActorByURL@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/utils/TabSources.js:237:11 ObjectActor.prototype._getSourceOriginalLocation@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/object.js:585:18 ObjectActor.prototype.onAllocationStack@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/object.js:561:22 DSC_onPacket@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/main.js:1598:15 LocalDebuggerTransport.prototype.send/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/transport/transport.js:569:11 makeInfallible/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/DevToolsUtils.js:83:14 makeInfallible/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/DevToolsUtils.js:83:14 EventLoop.prototype.enter@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:339:5 ThreadActor.prototype._pushThreadPause@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:531:5 ThreadActor.prototype._pauseAndRespond@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:732:7 ThreadActor.prototype.onDebuggerStatement@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:1791:9 makePromises@http://example.com/browser/browser/devtools/debugger/test/doc_promise-get-allocation-stack.html:21:9 this.call@chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:18:10 @chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:71:12 Promise*@chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:70:3 Line: 237, column: 11" {file: "resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/main.js" line: 1467}] onPacket threw an exception: Error: Server did not specify an actor, dropping packet: {"error":"unknownError","message":"error occurred while processing 'allocationStack: Error: getSourceByURL: could not find source for chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js\nStack: TabSources.prototype.getSourceActorByURL@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/utils/TabSources.js:237:11\nObjectActor.prototype._getSourceOriginalLocation@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/object.js:585:18\nObjectActor.prototype.onAllocationStack@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/object.js:561:22\nDSC_onPacket@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/main.js:1598:15\nLocalDebuggerTransport.prototype.send/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/transport/transport.js:569:11\nmakeInfallible/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/DevToolsUtils.js:83:14\nmakeInfallible/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/DevToolsUtils.js:83:14\nEventLoop.prototype.enter@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:339:5\nThreadActor.prototype._pushThreadPause@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:531:5\nThreadActor.prototype._pauseAndRespond@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:732:7\nThreadActor.prototype.onDebuggerStatement@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:1791:9\nmakePromises@http://example.com/browser/browser/devtools/debugger/test/doc_promise-get-allocation-stack.html:21:9\nthis.call@chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:18:10\n@chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:71:12\nPromise*@chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:70:3\nLine: 237, column: 11"} Stack: DebuggerClient.prototype.onPacket@resource://gre/modules/devtools/dbg-client.jsm:968:1 LocalDebuggerTransport.prototype.send/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/transport/transport.js:569:11 makeInfallible/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/DevToolsUtils.js:83:14 makeInfallible/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/DevToolsUtils.js:83:14 EventLoop.prototype.enter@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:339:5 ThreadActor.prototype._pushThreadPause@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:531:5 ThreadActor.prototype._pauseAndRespond@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:732:7 ThreadActor.prototype.onDebuggerStatement@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/script.js:1791:9 makePromises@http://example.com/browser/browser/devtools/debugger/test/doc_promise-get-allocation-stack.html:21:9 this.call@chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:18:10 @chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:71:12 Promise*@chrome://mochitests/content/browser/browser/devtools/debugger/test/code_frame-script.js:70:3 Line: 968, column: 1 https://treeherder.mozilla.org/#/jobs?repo=try&revision=8883a1cf791a
Attachment #8623104 - Attachment is obsolete: true
Attachment #8624538 - Flags: review?(nfitzgerald)
Comment on attachment 8624538 [details] [diff] [review] Part 10: Implement getAllocationStack method in ObjectClient [2.0] Review of attachment 8624538 [details] [diff] [review]: ----------------------------------------------------------------- Nice. ::: toolkit/devtools/server/actors/object.js @@ +584,5 @@ > + _getSourceOriginalLocation: function(stack) { > + let source; > + try { > + source = this.hooks.sources().getSourceActorByURL(stack.source); > + } catch(e) {} Document this catchall with a comment.
Attachment #8624538 - Flags: review?(nfitzgerald) → review+
Comment on attachment 8624860 [details] [diff] [review] Part 13: Add test for asserting the Promise allocation stack in chrome debugging [1.0] Review of attachment 8624860 [details] [diff] [review]: ----------------------------------------------------------------- ::: browser/devtools/debugger/test/browser.ini @@ +350,5 @@ > skip-if = e10s && debug > [browser_dbg_promises-allocation-stack.js] > skip-if = e10a && debug > +[browser_dbg_promises-chrome-allocation-stack.js] > +skip-if = e10a && debug "e10a"
Attachment #8624860 - Flags: review?(nfitzgerald) → review+
Attachment #8623107 - Attachment is obsolete: true
Attachment #8625822 - Flags: review+
Added requestLongerTimeout
Attachment #8624860 - Attachment is obsolete: true
Attachment #8625862 - Flags: review+
Attachment #8625819 - Flags: checkin+
Attachment #8625820 - Flags: checkin+
Attachment #8625822 - Flags: checkin+
Attachment #8625862 - Flags: checkin+
Keywords: leave-open
Depends on: 1177730
Depends on: 1192992
Blocks: 1438190
Product: Firefox → DevTools
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: