mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 08:45:46 +00:00
Bug 866231: Have the remote protocol profiler actor copy notification values and break cycles before sending them to the client. r=dcamp
This commit is contained in:
parent
4fd4d6ce30
commit
a31f97d54e
@ -99,35 +99,40 @@ ProfilerActor.prototype = {
|
||||
return { unregistered: unregistered }
|
||||
},
|
||||
observe: makeInfallible(function(aSubject, aTopic, aData) {
|
||||
function unWrapper(obj) {
|
||||
if (obj && typeof obj == "object" && ("wrappedJSObject" in obj)) {
|
||||
obj = obj.wrappedJSObject;
|
||||
if (("wrappedJSObject" in obj) && (obj.wrappedJSObject == obj)) {
|
||||
/* If the object defines wrappedJSObject as itself, which is the
|
||||
* typical idiom for wrapped JS objects, JSON.stringify won't be
|
||||
* able to work because the object is cyclic.
|
||||
* But removing the wrappedJSObject property will break aSubject
|
||||
* for possible other observers of the same topic, so we need
|
||||
* to restore wrappedJSObject afterwards */
|
||||
delete obj.wrappedJSObject;
|
||||
return { unwrapped: obj,
|
||||
fixup: function() {
|
||||
this.unwrapped.wrappedJSObject = this.unwrapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* this.conn.send can only transmit acyclic values. However, it is
|
||||
* idiomatic for wrapped JS objects like aSubject (and possibly aData?)
|
||||
* to have a 'wrappedJSObject' property pointing to themselves.
|
||||
*
|
||||
* this.conn.send also assumes that it can retain the object it is
|
||||
* passed to be handled on later event ticks; and that it's okay to
|
||||
* freeze it. Since we don't really know what aSubject and aData are,
|
||||
* we need to pass this.conn.send a copy of them, not the originals.
|
||||
*
|
||||
* We break the cycle and make the copy by JSON.stringifying those
|
||||
* values with a replacer that omits properties known to introduce
|
||||
* cycles, and then JSON.parsing the result. This spends processor
|
||||
* time, but it's simple.
|
||||
*/
|
||||
function cycleBreaker(key, value) {
|
||||
if (key === 'wrappedJSObject') {
|
||||
return undefined;
|
||||
}
|
||||
return { unwrapped: obj, fixup: function() { } }
|
||||
return value;
|
||||
}
|
||||
var subject = unWrapper(aSubject);
|
||||
var data = unWrapper(aData);
|
||||
|
||||
/*
|
||||
* If these values are objects with a non-null 'wrappedJSObject'
|
||||
* property, use its value. Otherwise, use the value unchanged.
|
||||
*/
|
||||
aSubject = (aSubject && aSubject.wrappedJSObject) || aSubject;
|
||||
aData = (aData && aData.wrappedJSObject) || aData;
|
||||
|
||||
this.conn.send({ from: this.actorID,
|
||||
type: "eventNotification",
|
||||
event: aTopic,
|
||||
subject: subject.unwrapped,
|
||||
data: data.unwrapped });
|
||||
data.fixup();
|
||||
subject.fixup();
|
||||
subject: JSON.parse(JSON.stringify(aSubject, cycleBreaker)),
|
||||
data: JSON.parse(JSON.stringify(aData, cycleBreaker)) });
|
||||
}, "ProfilerActor.prototype.observe"),
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user