[Laszlo-dev] For Review: Change 20070930-ptw-P Summary: Don't trust length as an indicator of array elements
P T Withington
ptw at pobox.com
Mon Oct 15 17:48:59 PDT 2007
On 2007-10-03, at 18:00 EDT, André Bargull wrote:
> If got a couple of questions regarding this changeset:
> 1. Debug.write([void(0)]) will now print "[undefined]", beforehand
> it was "[...]"
> Undefined values were explicitly skipped prior to this change
> (see i.e. LzDebug.as (old), ll.358: /"skip non-existent elements"/)
> This behaviour has changed => intentionally or not?
This is actually a correction. In very old swf runtimes, you could
not tell the difference between a non-existent property and a
property whose value is undefined. Now we can, so I think it is more
honest for the debugger to print these properties than to skip them.
> 2. Debug.write({length:'0'}) will now print "«Object#0| []»",
> beforehand it was "{length: 0}"
> Additional test for type of the length-attribute, "string" vs.
> "number"?
Good point. I will fix that.
> 3. SWF vs. DHTML: to create a common code base, you've removed some
> try..catch blocks (see LzDebug.js (old), l.462 to l.483)
> Any disadvantages possible through this change?
I think the advantages out-weigh the disadvantages. A) I put that
particular try/catch in early on when I was just trying to get the
debugger working at all in DHTML, B) It seems bad form to just
discard errors silently. Finally, now that we have Firebug, if we do
hit an error here, hopefully we can fix it.
> 4. SWF vs. DHTML: /"getter-heuristic"/ Debug#inspectInternal(..)
> resp. Debug#objectOwnProperties(..),
> less tests in SWF and
> removed try..catch in DHTML, no disadvantages at all for this?
> SWF:
> if ((! hasProto) ||
> obj.hasOwnProperty(key) ||
> // attached movie clips don't show up as
> 'hasOwnProperty' (but
> // hasOwnProperty is more accurate -- consider if an
> instance
> // copies a prototype property)
> (obj[key] !== obj.__proto__[key]) ||
> // or getter slots (this is a heuristic -- there is no
> way to
> // ask if a property is a getter)
> *(obj.__proto__.hasOwnProperty(key) &&
> (typeof(obj.__proto__[key]) == 'undefined'))*
> )
>
> DHTML:
> if ((! hasProto) ||
> obj.hasOwnProperty(key) ||
> // or getter slots (this is a heuristic -- there is no
> way to
> // ask if a property is a getter)
> *(function () { try { return obj[key] } catch (e) {} })
> () !==
> (function () { try { return obj.constructor.prototype
> [key] } catch (e) {} })()*
> )
>
> NEW:
> if ((! hopp) ||
> obj.hasOwnProperty(key) ||
> // Heuristic to find getter slots (there is no way to
> ask if a
> // property is a getter)
> (proto && (obj[key] !== proto[key])))
I am pretty sure that the new test subsumes both heuristics. Any
time the value of a property in an object is different from that same
property in the object's prototype, it is probably 'interesting' to
the debugger. I'm not trying to be perfect here in any case, I am
just trying to show the properties of an object, but not show
zillions of inherited properties (they are probably less interesting).
It's not an error in JS to ask for a non-existent property, so the
try/catches should be superfluous. They probably have the same
origin as the one discussed above: just inserted randomly to try to
get the debugger working.
> 5. Debug#__String(..): changes for treatment of objects with a
> (numeric) "length" property.
> Beforehand: any object with a numeric length property was
> treated as an array, "toString()" was never called,
> see i.e. LzDebug.as (old), l.349 and ll.376
> Now: if any object has got an own "toString()" method, it
> will called, so no treatment as an array,
> see i.e. LzDebug.as (new), ll.348 and ll.360
> Good change, but do we need to document it?
In general I have not been documenting this level of cosmetic change
in the debugger -- I guess now that there are lots of users out
there, I should be more deliberate. Do you think it important to
document this level of change? I tend to think of the debugger as
constantly evolving and it not being critical that minor changes like
this be documented.
> Improvements:
> - LzDebug.as, l.349 (new), "(thing['toString'] instanceof Function)
> &&" ==> "(thing.toString instanceof Function) &&"
> - LzDebug.as, l.563 (old), "var kl = keys.length;", LzDebug.as, l.
> 541 (new), "var kl = names.length;"
> "kl = [k]eys.[l]ength", but "kl = names.[l]ength"? (also for
> "var kil" and the same vars in LzDebug.js)
> Could be changed for clarification...
Noted. Will fix.
> Bug?:
> - LzDebug.js, l.289 (new), "(this.toString instanceof Function)"
> should be "(thing.toString instanceof Function)"!?
Well spotted! Thanks!
> P T Withington wrote:
>> [André, if you are not up for reviewing this, let me know and I
>> will get someone else, but I thought you might be an interested
>> party...]
>>
>> Change 20070930-ptw-P by ptw at dueling-banjos.local on 2007-09-30
>> 18:01:29 EDT
>> in /Users/ptw/OpenLaszlo/ringding-2
>> for http://svn.openlaszlo.org/openlaszlo/trunk
>>
>> Summary: Don't trust length as an indicator of array elements
>>
>> Bugs Fixed:
>> LPP-4441 'Debugger misbehaves when debugging objects with "length"
>> attribute.'
>>
>> Technical Reviewer: a.bargull at intensis.de (pending)
>> QA Reviewer: hminsky (pending)
>> Doc Reviewer: jsundman (pending)
>>
>> Documentation:
>> NOTE: If you have Firebug enabled in Firefox, the LZX debugger echos
>> all messages to the Firebug console, preserving objects. The Firebug
>> debugger will attempt to interpret an object with a `length` field as
>> an array and try to print every array element. This may cause a
>> 'Script Running Slowly' error. Disabling Firebug will prevent that.
>>
>> Details:
>> Don't trust length to indicate how many properties are in an
>> object (or elements in an array). Instead, get the properties
>> from the object using `for ... in`. We still present any object
>> with a `length` property that is non-negative as an array, but we
>> won't try to iterate through the entire array. This is useful
>> for
>> sparse arrays, but also for objects that just happen to have a
>> non-negative length property.
>>
>> LzDebug.lzs: Added Debug.objectOwnProperties that gets the names
>> of all the 'own' properties of the object. If the object has a
>> non-negative `length` property, accumulate the properties that
>> are
>> between 0 and that length in a separate list of indices.
>>
>> LzDebug.{as,js}: Use that to print and inspect objects and
>> arrays
>> without falling into the trap of iterating from 0 to length.
>> Basically, the old presentation style is preserved, but we
>> iterate
>> _only_ over the properties the object actually has.
>>
>> Tests:
>> lzx> Debug.write({1: 'one', 97: 'ninety-seven', a: 'eh?',
>> floogle: 'snort', length: 100000000, __proto__: {bar: 'bletch'}})
>> «Object(100000000)#127| [..., one, ..., ninety-seven]»
>> lzx> Debug.inspect([..., one, ..., ninety-seven])
>> «Object(100000000)#127| [..., one, ..., ninety-seven]» {
>> a: 'eh?'
>> floogle: 'snort'
>> length: 100000000
>> 1: 'one'
>> 97: 'ninety-seven'
>> }
>> [..., one, ..., ninety-seven]
>> lzx>
>>
>> Above completes without "Script Running Slowly". Tested in SWF
>> and DHTML (with Firebug disabled, see Documentation NOTE above).
>>
>> smokecheck passes in DHTML and SWF (which tests Debug.format,
>> which uses __String, showing that the expected presentation is
>> preserved).
>>
>> Files:
>> M WEB-INF/lps/lfc/debugger/LzDebug.lzs
>> M WEB-INF/lps/lfc/debugger/platform/swf/LzDebug.as
>> M WEB-INF/lps/lfc/debugger/platform/dhtml/LzDebug.js
>>
>> Changeset: http://svn.openlaszlo.org/openlaszlo/patches/20070930-
>> ptw-P.tar
>>
More information about the Laszlo-dev
mailing list