From: kangax on
On 1/12/10 11:22 AM, Richard Cornford wrote:
> On Jan 12, 3:20 pm, Scott Sauyet wrote:
> <snip>
>> I modified your example here, using Thomas' code, modified to
>> put the elements in the document of the inner frame:
>>
>> http://scott.sauyet.com/Javascript/Demo/2010-01-12a/
>>
>> This has an error in IE which I haven't chased down. Anyone
>> know why IE reports an "Unexpected call to method or property
>> access" on the append child call for the style element?
>
> In IE (from about version 5) elements have a boolean - canHaveChildren
> - property, which is false for some types of elements, including
> SCRIPT and STYLE elements. Elements with false - canHaveChildren -
> properties cannot have children and so attempts to append children to
> them throw exceptions. Obviously this condition is testable, so
> changing relevant section of your function to:-
>
> var s2 = frameDoc.createElement("style");
> if (s1&& s2){
> frameHead.appendChild(s2);
> s2.type = "text/css";
> if(
> (typeof s2.canHaveChildren != 'boolean')||
> (s2.canHaveChildren)
> ){
> s2.appendChild(
> frameDoc.createTextNode(
> s1.cssText || s1.ownerNode.textContent
> )
> );
> }else if(
> (typeof s2.styleSheet == 'object')&&

`typeof ... == "object"` is a somewhat unsafe existence test.

In Internet Explorer (at least 8), there's "Enable DOM Storage" option.
When that option is unchecked, `window.localStorage` evaluates to
`null`. Obviously, `typeof window.localStorage` then evaluates to
"object" (and `"localStorage" in window` evaluates to `true`, although
this is unrelated to example at hand).

It seems unlikely that IE is to ever introduce such possibility, but if
they do (or for whatever other reason), there's a chance of
`s2.styleSheet` being `null` and `typeof s2.styleSheet == 'object'`
evaluating to `true` in your example. In that case, following line would
result in an error.

Alternatives that come to mind:

// direct test for `null` value
if (typeof s2.styleSheet == "object" && s2.styleSheet !== null)

// boolean type conversion with typeof check before, to avoid type
converting "unknown" objects
if (typeof s2.styleSheet == "object" && s2.styleSheet)

// or just boolean type conversion (probably most unsafe one)
if (s2.styleSheet)


> (typeof s2.styleSheet.cssText == 'string')
> ){
> s2.styleSheet.cssText = (
> s1.cssText || s1.ownerNode.textContent
> );
> }
> }

[...]

--
kangax
From: Richard Cornford on
On Jan 18, 10:15 pm, kangax wrote:
> On 1/12/10 11:22 AM, Richard Cornford wrote:
>> On Jan 12, 3:20 pm, Scott Sauyet wrote:
<snip>
>>> This has an error in IE which I haven't chased down. Anyone
>>> know why IE reports an "Unexpected call to method or property
>>> access" on the append child call for the style element?
>
>> In IE (from about version 5) elements have a boolean -
>> canHaveChildren - property, which is false for some types of
>> elements, including SCRIPT and STYLE elements. Elements with
>> false - canHaveChildren - properties cannot have children and
>> so attempts to append children to them throw exceptions.
>> Obviously this condition is testable, so changing relevant
>> section of your function to:-
>
>> var s2 = frameDoc.createElement("style");
>> if (s1&& s2){
>> frameHead.appendChild(s2);
>> s2.type = "text/css";

In retrospect I was thinking that the order here probably was not a
good idea. That is, it probably would be better to assign the - type -
prior to appending the element to the DOM.

>> if(
>> (typeof s2.canHaveChildren != 'boolean')||
>> (s2.canHaveChildren)
>> ){
>> s2.appendChild(
>> frameDoc.createTextNode(
>> s1.cssText || s1.ownerNode.textContent
>> )
>> );
>> }else if(
>> (typeof s2.styleSheet == 'object')&&
>
> `typeof ... == "object"` is a somewhat unsafe existence test.

That would depend on what you know at the point of making the test. It
isn't a great test here but we know that it is not going to be
executed unless the environment in question either is a known IE 5+ or
is trying pretty hard to imitate one.

> In Internet Explorer (at least 8), there's "Enable DOM Storage"
> option. When that option is unchecked, `window.localStorage`
> evaluates to `null`. Obviously, `typeof window.localStorage`
> then evaluates to "object" (and `"localStorage" in window`
> evaluates to `true`, although this is unrelated to example
> at hand).
>
> It seems unlikely that IE is to ever introduce such possibility,
> but if they do (or for whatever other reason), there's a chance
> of `s2.styleSheet` being `null` and
> `typeof s2.styleSheet == 'object'` evaluating to `true` in your
> example. In that case, following line would result in an error.

Yes it would, unless in the meanwhile Microsoft change IE such that
the STYLE elements accept the setting of their content via the
insertion of a Text Node, in which case the value of - canHaveChildren
- changes to true and the browser never uses that second branch. That
seems quite a plausible change as people really do seem to like the
idea of creating SCRIPT and STYLE elements using DOM creation methods
(though I always note that it is TextNodes that get appended rather
than CDATASection Nodes getting any consideration (maybe a reflection
of the fact that there is not nearly as much XHTML in existence as the
impression that may be gained from looking at mark-up)).

> Alternatives that come to mind:
>
> // direct test for `null` value
> if (typeof s2.styleSheet == "object" && s2.styleSheet !== null)
>
> // boolean type conversion with typeof check before, to avoid type
> converting "unknown" objects
> if (typeof s2.styleSheet == "object" && s2.styleSheet)
>
> // or just boolean type conversion (probably most unsafe one)
> if (s2.styleSheet)
>
>> (typeof s2.styleSheet.cssText == 'string')
>> ){
<snip>

Yes, there are alternatives, all more complex. In a general sense I
don't like the need to repeat this test when the thing that is being
tested is not going to change while the document is loaded. Re-
designing the code so that it only tested once and branched to, say,
assign one of two STYLE Element content assigning functions for later
use would make more elaborate testing more appealing.

But there is minimal worth in devoting time to this code. It is, after
all (and as has been pointed out), solving the problem in the worst
way possible (or solving the wrong problem).

Richard.