Should isHostMethod be added to the FAQ?

G

Garrett Smith

[-about isHost* methods-]
These three functions depend on non-standardized behavior of the
typeof operator. The typeof operator is being used as some sort of
magic try-catch but the ECMAScript standard doesn't say anything about
that behavior. From my reading of the standard if obj.prop blows up in
some browser than so could typeof(obj.prop). It just so happens that
the implementations don't blow up when using the typeof version.

In what way does |typeof| seems magic? If the answer to that has not
been explained clearly, it can be, and doing so would be worthwhile.

Garrett
 
T

Thomas 'PointedEars' Lahn

kangax said:
Thomas said:
kangax said:
Thomas 'PointedEars' Lahn wrote:
The local version of object.js (0.1.5a.2009062116) currently features
jsx.object.isMethod() which allows to pass an object reference plus an
arbitrary number of string arguments. This allows e.g. isMethod(Array,
"prototype", "slice", "call") and avoids repeated calls of isMethod().
This sounds useful. Another common need is to test multiple methods on
the same base object, so these two (i.e. your n-level `isMethod` and
`areMethods`) might cover most of the use cases:

[...]
areMethods(document, 'body', ['appendChild', 'removeChild']);
Conceptionally, I like this approach best. Not much overloading and very
flexible. However, an Array object reference (which requires a reliable
Array test¹) should only be allowed as last argument to avoid expensive
backtracking; or do you have an idea for that as well?

Yes, an array as last argument is what I had in mind. Allowing it as any
argument seems impractical and unnecessarily expensive (i.e.
backtracking cost which you mentioned).

ACK. Implemented and tested OK last night so:

for (var i = 1; i < len; i++)
{
var
p = arguments,
p_is_Array = (i === len - 1 && jsx.object.isArray(p)),
origP = p;

for (var j = (p_is_Array && origP.length || 1); j--;)
{
if (p_is_Array) p = origP[j];

t = typeof o[p];

// ...
}
}

Did I miss something?
¹ Regarding the cross-frame issue: what about a property referring
to the current Array object to be set and reset before/after call
as needed?

I suppose you're talking about so-called Miller device (i.e. comparing
value of [[Class]] to "Array").

Yes, I don't like that for its many assumptions.
From what I remember (per Richard's observations), it was
*cross-window issue*, not cross-frame one.

But I thought the problem were different global objects, each with its own
Array property.
In any case, I'm not sure I understand what you mean by resetting
property and "current Array object". Would you please clarify?

/**
* Reference to the object used for {@link Array} detection;
* modify at runtime if you access this script from
* a different frame.
*/
jsx.Array = typeof Array != "undefined" ? Array : null;

/**
* NOTE: This method has previously been provided by
* {@link types.js}; optimizations in code reuse moved it here.
*
* @author
* (C) 2003, 2009 Thomas Lahn &lt;[email protected]&gt;
* @partof http://pointedears.de/scripts/object.js
* @requires jsx#object.isInstanceOf
* @param a : Object
* Expression to be determined an array.
* @return
* <code>true</code> if <code>a</code> is an object
* derived from Array, <code>false</code> otherwise.
* Returns also <code>false</code> if the language
* version does not support Array objects (JavaScript
* before 1.1).
*/
var isArray = jsx.object.isArray = function(a) {
return jsx.object.isInstanceOf(a, jsx.Array);
};
I assumed `document` would be tested for existence before performing
that test.

That is exactly what I want to avoid.
Or if it wasn't, it should always be possible to "start" from
the global object:

// considering `this` refers to Global Object here:
isMethod(this, 'window', 'document', 'body', 'appendChild');

Yes, I am using

jsx.object.isMethod(jsx.global, 'window', 'document', 'body', 'appendChild');

But a method to be tested is not necessarily anchored at the global object.
This actually gave me an idea for alternative `isMethod` signature:

isMethod('window.document.body.appendChild');

would split string by ".", then sequentially test properties starting
from the global object. Not sure how this would work with multiple
methods though (i.e. `areMethods`).

I had considered and rejected this approach already because it would
preclude property names with dots in them from being considered.
As far as type converting host objects (not methods!), didn't we just
have a conversation about it where you said that it should be safe to do so?

[...]
<http://groups.google.com/group/comp.lang.javascript/msg/4df3cf9b5a7bd60f>

Or am I missing something?

Yes, I was talking about return values of standardized methods there.
What do you mean by "flag" and "per flag"?

/**
* ...
*
* @param statements
* Value to be evaluated as a <i>StatementList</i>.
* Called if a <code>Function</code> object reference, converted
* to string if not a string, and used as-is otherwise.
* For compatibility, the <code>undefined</code> value
* is evaluated like the empty string.
* @param errorHandlers
* Value to be evaluated as a <i>StatementList</i> in case of an
* exception. Called if a <code>Function</code> object reference,
* converted to string if not a string, and used as-is otherwise.
* For compatibility, the <code>undefined</code> value
* is evaluated like the empty string.
* @return
* The result of <code>statements</code>, or the result
* of <code>errorHandlers</code> if an error occurred.
* @author
* Copyright (c) 2008
* Thomas 'PointedEars' Lahn &lt;[email protected]&gt;
* Distributed under the GNU GPL v3 and later.
* @partof JSX:eek:bject.js
*/
var tryThis = jsx.tryThis = function(statements, errorHandlers) {
/**
* @param s Value to be stringified
* @param sIdent Identifier of the value to be stringified
* @return string Stringified version of <code>s</code>
*/
function stringify(s, sIdent)
{
if (typeof s == "function")
{
s = sIdent || "(" + s + ")()";
}
else if (typeof s == "undefined")
{
s = "";
}

return s;
}

var sStatements = stringify(statements, "statements();");
var sErrorHandlers = stringify(errorHandlers, "errorHandlers(e);");

var code = 'try {\n ' + sStatements + '\n}\n'
+ 'catch (e) {\n ' + sErrorHandlers + '\n}';

return eval(code);
};

/* ... */

var isMethod = jsx.object.isMethod = jsx.object.areMethods = function(o, p) {
var len = arguments.length;
if (len < 1) return false;

var
rxUnknown = /^\s*unknown\s*$/i,
rxMethod = /^\s*(function|object)\s*$/i,
t = typeof o;

/* ... */

/*
* Refined support for strings; evaluating them always would
* preclude String objects from being tested for methods.
* Try to warn if a primitive string value is passed and the
* required flag is not set (default).
*/
if (t === "string")
{
if (arguments.callee.evalStrings)
{
/*
* Only consider strings that could be property accessors (incl. E4X)
* TODO: Unicode identifiers
*/
if (/^\s*\w+(\s*\.\.?\s*\w+|\[[^]]+\])*\s*$/.test(o))
{
o = jsx.tryThis(o);
}
else
{
jsx.dmsg(
"jsx.object.isMethod: string does not look like"
+ " a property access; using it as-is",
"warn");
}
}
else
{
jsx.dmsg(
"jsx.object.isMethod: Evaluation of strings requires"
+ " .evalStrings == true",
"warn");
}
}

/* ... */
};

/**
* Set this flag to <code>true</code> to allow evaluation
* of primitive strings as first argument. Allows for
* isMethod("foo", "bar") without testing the type of `foo' first.
* The default is <code>false</code>.
*/
isMethod.evalStrings = false;


PointedEars
 
T

Thomas 'PointedEars' Lahn

Peter said:
[...]
Feature Detection: State of the Art Browser Scripting
<URL:http://peter.michaux.ca/articles/feature-detection-state-of-the-art-b...

[isHostMethod, isHostCollection, and isHostObject functions]
These three functions depend on non-standardized behavior of the
typeof operator. The typeof operator is being used as some sort of
magic try-catch but the ECMAScript standard doesn't say anything about
that behavior. From my reading of the standard if obj.prop blows up in
some browser than so could typeof(obj.prop). It just so happens that
the implementations don't blow up when using the typeof version.

But not merely by chance.

,-[ECMAScript Language Specification, Edition 3 Final]
|
| 11.2.1 Property Accessors 11.4.3 The typeof Operator
|
| [...]
| The production The production
|
| MemberExpression : UnaryExpression :
| MemberExpression typeof UnaryExpression
| [ Expression ]
|
| is evaluated as follows: is evaluated as follows:
|
| 1. Evaluate MemberExpression. 1. Evaluate UnaryExpression.
| 2. If Type(Result(1)) is not
| Reference, go to step 4.

| 3. If GetBase(Result(1)) is null,
| return "undefined".
| 2. Call GetValue(Result(1)). 4. Call GetValue(Result(1)).
| 3. Evaluate Expression.
| 4. Call GetValue(Result(3)).
| 5. Call ToObject(Result(2)).
| 6. Call ToString(Result(4)).
| 7. Return a value of type 5. Return a string determined
| Reference whose base object by Type(Result(4)) according
| is Result(5) and whose to the following table:
| property name is Result(6).
| Type Result
| --------------------------------
| Undefined "undefined"
| Null "object"
| Boolean "boolean"
| Number "number"
| String "string"
|
| Object (native "object"
| and doesn’t
| implement
| [[Call]])
|
| Object (native "function"
| and implements
| [[Call]])
|
| Object (host) Implementation-
| dependent


PointedEars
 
P

Peter Michaux

Peter said:
[...]
Feature Detection: State of the Art Browser Scripting
<URL:http://peter.michaux.ca/articles/feature-detection-state-of-the-art-b...
[isHostMethod, isHostCollection, and isHostObject functions]
These three functions depend on non-standardized behavior of the
typeof operator. The typeof operator is being used as some sort of
magic try-catch but the ECMAScript standard doesn't say anything about
that behavior. From my reading of the standard if obj.prop blows up in
some browser than so could typeof(obj.prop).  It just so happens that
the implementations don't blow up when using the typeof version.

But not merely by chance.

[Snip sections 11.2.1 and 11.4.3 of the ECMAScript standard quoted in
an awkward-to-reply-to, two-column format.]

Look more into the evaluation of step 4 of the typeof operator. It is

4. Call GetValue(Result(1))

GetValue depends on the behavior specified in section 8.7.1 which
contains

4. Call the [[Get]] method of Result(2), ...

where Result(2) is the host object being tested for a property.

Then look at section 8.6.2 just before 8.6.2.1 which discusses the
requirements on [[Get]] (and other internal properties) for host
objects.

Host objects may implement these methods in any manner unless
specified otherwise.

Since it is not specified otherwise, [[Get]] for a host object could
throw an error.

There is no way to know what step 4 of a typeof evaluation will do and
there is no provision in the specification of typeof to protect
against the situation where an error is thrown.

This means that typeof(hostobj.prop) could throw an error.

Peter
 
T

Thomas 'PointedEars' Lahn

wilq said:
Thomas said:
wilq said:
I dont have access to mine profiling function so I create own one
from scratches. Its not great because I do this in hurry, if you have
time to test it - please do. If you have idea on what might
interferee with test cases - i'm open to hear :) Cheers:
[...]
(function(){
var times=[];
function addTime()
{
times.push((new Date()).getTime());
Why, +new Date() suffices.

If we use it every time when measuring - it is counted inside measurement
time for both operation (regexp and string)... so what diffrence?

+new Date() is arguably more runtime-efficient than (new Date()).getTime(),
another explicit method call (untested). Historically, type-converting
operations have been more runtime-efficient than type-converting calls.
Yes of course - because of this is an argument that you can change.

The question raised by this is: Is it realistic for an app to perform that
many calls of isMethod() consecutively? If not, the number is too high.
And as it is too high (IMHO), differences in runtime efficiency between
these approaches are in fact not as important as you present them to be.
And, as I said, efficiency is not everything. To begin with, any approach
should balance efficiency against reliability.
You can add those bracers to mine profiling function. As you probably
notice this does not change alot.

Yes, as written in e-mail, with realistic figures the difference is as
negligible as before (in the 50 ms range on a Pentium M 740).
Cheater ? I dont think so - I compare here cases that will occur mostly -
"function" and "object". But I do the same for string solution

No, you don't.
so there is no cheat. In fact its very fair comparsion in mine opinion.

Hardly. Fair would be

someTemp = regExp.test(a) || regExp.test(b);
I open to see a best + worst case as you said that is in string
comparsion.

The problem is that you are picking the cases that are in your favor,
IOW you *are* cheating here.
Yes - this is a idea of this test.

This test is biased(, then).
I propose this test as a answer to post from some time ago that
You were involved in:

Correct me if I'm wrong, you changed:

basically you changed there

(t=='function' || t=='object')

to:

/^(function|object)$/.test(t)

You are wrong. Both about the original and the change.
So here I also did the test. And in post before I explained why this
string comparsion would be better - exacly that if a first boolean
structure will be true, second wont be computed at all. You can try
diffrent cases (both worst, both good) with a="object", b="object" and
a="function", b="function" to see that this is still faster than
regexp...

*Maybe* so, on *your* computer, *without RegExp optimization*. But it is
on *all* computers (running non-obsolete implementations) *less reliable*.
If this is really so big diffrence for you ?

Yes, it is.
Then please consider this for the code that I gave:

var a=typeof (function(){});
var b=typeof ({someObject:0});

I was talking about host objects.
Basically you pointed out some elements in code, but generally that has
nothing to do with really results of test.

Yes, it does. We are not discussing in a theoretical vacuum here.
Efficiency considerations matter because practical issues arise from
following an inefficient approach.
Also you did not provide anything that would show that this approach is
completly wrong. Please then provide code that proves what you saying is
true :) I really like seeing things working than only talking. Then I
can judge your solution :)

I have posted and pointed to the current (abridged) isMethod()
implementation already; now you only need to notice that.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Peter said:
Thomas said:
Peter said:
[...]
Feature Detection: State of the Art Browser Scripting
<URL:http://peter.michaux.ca/articles/feature-detection-state-of-the-art-b...
[isHostMethod, isHostCollection, and isHostObject functions]
These three functions depend on non-standardized behavior of the
typeof operator. The typeof operator is being used as some sort of
magic try-catch but the ECMAScript standard doesn't say anything about
that behavior. From my reading of the standard if obj.prop blows up in
some browser than so could typeof(obj.prop). It just so happens that
the implementations don't blow up when using the typeof version.
But not merely by chance.

[Snip sections 11.2.1 and 11.4.3 of the ECMAScript standard quoted in
an awkward-to-reply-to, two-column format.]

It was posted like that (with considerable effort!) so that the differences
could be easily seen by the dedicated reader. Not awkward at all.
Look more into the evaluation of step 4 of the typeof operator. It is

4. Call GetValue(Result(1))

(JFTR: I have not doubted that the observed behavior may be the result of
not standards-compliant parts in the respective implementation of ECMAScript
or the DOM's ECMAScript binding.)

FWIW, I don't think GetValue() matters here. While step 3 of the `typeof'
algorithm could matter (which would be not standards compliant as it MUST
NOT return "unknown"), I think it matters more what actually happens in
steps 3 to 6 of the property accessor algorithm. Also the ToBoolean() in
the `if' statement algorithm (12.5) deserves closer inspection.
[...]
This means that typeof(hostobj.prop) could throw an error.

JFTR: Yes, it could.


PointedEars
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]>, Thu,
+new Date() is arguably more runtime-efficient than (new Date()).getTime(),
another explicit method call (untested). Historically, type-converting
operations have been more runtime-efficient than type-converting calls.

An excellent demonstration of the relative powers of arguing and of
getting actual facts.

Time taken by D.getTime(), as percentage of time for +D, if I tested
correctly :

IE 7 85
FF 3.0.11 85
Op 9.64 43
Safari 4.0 65
Chrome 2.0 29

Testing with new Date() gives rather irregular results, presumably
because of the many OS calls; but supports the conclusion.

Using getTime calls explicitly for use of that Method; using unary +
calls implicitly for the use of method valueOf, presumably the same
code, and also does the "return a Number" operation, apparently not
optimising it out.

But I suggest that testing is not needed to see that unary + is faster
to type and to read.

Did that speed difference not get mentioned here before, not so long
ago?
 
D

David Mark

RobG said:
<FAQENTRY>
There has been frequent mention of the legendary "isHostMethod"
function in this group over the last 18 months or so in conjunction
with statements that "boolean type conversion is out" for testing host
method availability.  While that may be so, trying to find the elusive
method in all the noise is pretty difficult.
I discovered this version posted by Thomas in February 2008[1]:

My JSdoc™ says:

 * @author
 *   (C) 2003-2009  Thomas Lahn &lt;[email protected]&gt;

Oh mercy. You wrote that comment. Looking at the posted code, I will
concede that it's slightly modified from the one found in My Library
(mine creates the RegExp once.)
I presume Google Groups still has the first version, either here or in
de.comp.lang.javascript.

Huh? The first version(s) were posted here during the CWR
discussions.

[snip]
 
D

David Mark

RobG said:
RobG wrote:
I guess you mean this one:
Feature Detection: State of the Art Browser Scripting
<URL:http://peter.michaux.ca/articles/feature-detection-state-of-the-art-b...
If on one volunteers in the meantime, I'll make a start and post it
No, don't.
I suppose that means you wish to write the article yourself, [...]
What the FAQ item needs to convey is that it is practically impossible
to write a general "isObjectPropertyCallable" function to detect if a
method is callable or not (leaving out the use of try..catch as a
general solution).  What is reasonable is to use typeof for native
methods, and to use isHostMethod for host methods that should be
callable and available if the UA supports certain W3C DOM
specifications. The isHostMethod as discussed in clj is not intended
to be used as a general tool to determine if any random object or
property name is callable.
No, it is not a matter of wanting to write it myself.
Function isHostMethod is not a frequently asked question.

A search in GG for "isHostMethod" returns over 230 responses, the
first in February 2008. I think that qualifies at least as a frequent
topic.  I don't think an FAQ is necessarily based on actual questions
being asked, but rather frequent answers that are, or are expected to
be, given.  When was the last time someone asked "Why are my rollovers
so slow?".

No one has posted to this thread to say there is no need for the item,
it represents a step forward in feature detection of host methods and
the topic has come up a number of times recently. That is sufficient
to prompt consideration for inclusion in the FAQ - so that it can be
referenced and provide a definitive statement about the topic.

No doubt about it. Can also be found in many newer libraries.
It takes a draft FAQ item for that? ;-)

His "arguments" make no sense.
The only minor quibble I see here is over whether a regular expression
should be used or not - that is a relatively trivial matter related to
performance, not the purpose or overall design. I know you have a
personal opinion that the in operator should be used, but that is a
minority view.

It's apples and oranges anyway.

LOL. It basically comes down to two points. Doesn't like the name
and can't bottle his solution.
That is your opinion, and while you may be the FAQ maintainer, that
does not make you sole arbiter of what it should or should not
contain.
The purpose and limitations of the function have been
expressed (and summarised previously in this thread), they should be
part of the entry.

Agreed on both points.
There is no need for you to participate in the discussion, there are
half a dozen regulars who have already done so since the topic was
first raised. It only requires someone to post a draft, discussion to
occur, and suitable agreement be reached. It is then up to the FAQ
maintainer to put it in the FAQ.

Or we'll get rid of him and get one who will. :) And I think a
change is long overdue anyway.
 
T

Thomas 'PointedEars' Lahn

David said:
Thomas said:
RobG said:
<FAQENTRY>
There has been frequent mention of the legendary "isHostMethod"
function in this group over the last 18 months or so in conjunction
with statements that "boolean type conversion is out" for testing host
method availability. While that may be so, trying to find the elusive
method in all the noise is pretty difficult.
I discovered this version posted by Thomas in February 2008[1]:
My JSdocâ„¢ says:

* @author
* (C) 2003-2009 Thomas Lahn &lt;[email protected]&gt;

Oh mercy. You wrote that comment.

Because it's true.
Looking at the posted code, I will concede that it's slightly modified
from the one found in My Library (mine creates the RegExp once.)

It is not surprising that different people, at different times, independent
from one another, can come to the same result. My isMethod() is not any
more modified from that in your "My Library" (confusing name, isn't it?)
than vice-versa (it is _not_). I will ask you only once to stop implying
otherwise.
Huh? The first version(s) were posted here during the CWR
discussions.

No, years before that. IIRC, even years before Peter and you found cljs (at
least before you were *posting* here).


PointedEars
 
D

David Mark

David said:
Thomas said:
RobG wrote:
<FAQENTRY>
There has been frequent mention of the legendary "isHostMethod"
function in this group over the last 18 months or so in conjunction
with statements that "boolean type conversion is out" for testing host
method availability.  While that may be so, trying to find the elusive
method in all the noise is pretty difficult.
I discovered this version posted by Thomas in February 2008[1]:
My JSdoc™ says:
 * @author
 *   (C) 2003-2009  Thomas Lahn &lt;[email protected]&gt;
Oh mercy.  You wrote that comment.

Because it's true.

Sort of.
It is not surprising that different people, at different times, independent
from one another, can come to the same result.  My isMethod() is not any
more modified from that in your "My Library" (confusing name, isn't it?)
than vice-versa (it is _not_).  I will ask you only once to stop implying
otherwise.



No, years before that.  IIRC, even years before Peter and you found cljs (at
least before you were *posting* here).

That was certainly not isHostMethod as that is what I named my
function. Yours did not have the bit about "unknown" types, which
were apparently my discovery (every time I bring them up it seems
nobody knows what I am talking about.)

It is based on isMethodType from years back. And I "found" CLJ in
1996. Posted many times in the 90's as well, though not regularly and
probably under some silly handle.
 
D

David Mark

Thomas said:
kangax said:
Thomas 'PointedEars' Lahn wrote:
kangax wrote:
Thomas 'PointedEars' Lahn wrote:
The local version of object.js (0.1.5a.2009062116) currently features
jsx.object.isMethod() which allows to pass an object reference plusan
arbitrary number of string arguments.  This allows e.g. isMethod(Array,
"prototype", "slice", "call") and avoids repeated calls of isMethod().
This sounds useful. Another common need is to test multiple methods on
the same base object, so these two (i.e. your n-level `isMethod` and
`areMethods`) might cover most of the use cases:
[...]
areMethods(document, 'body', ['appendChild', 'removeChild']);
Conceptionally, I like this approach best.  Not much overloading and very
flexible.  However, an Array object reference (which requires a reliable
Array test¹) should only be allowed as last argument to avoid expensive
backtracking; or do you have an idea for that as well?
Yes, an array as last argument is what I had in mind. Allowing it as any
argument seems impractical and unnecessarily expensive (i.e.
backtracking cost which you mentioned).
ACK.  Implemented and tested OK last night so:
  for (var i = 1; i < len; i++)
  {
    var
      p = arguments,
      p_is_Array = (i === len - 1 && jsx.object.isArray(p)),
      origP = p;

    for (var j = (p_is_Array && origP.length || 1); j--;)
    {
      if (p_is_Array) p = origP[j];
      t = typeof o[p];
      // ...
    }
  }
Did I miss something?

Looks good. You could take `len - 1` out of the loop as well as avoid
resolving `jsx.object.isArray` over and over, but that is an
insignificant quibble (considering that number of arguments are unlikely
to exceed 4-5).


¹ Regarding the cross-frame issue: what about a property referring
  to the current Array object to be set and reset before/after call
  as needed?
I suppose you're talking about so-called Miller device (i.e. comparing
value of [[Class]] to "Array").
Yes, I don't like that for its many assumptions.

There are not so many assumptions. It works as designed with native
objects in compliant implementations. Host objects are of course allowed
to implement any [[Class]] value in ES3, but not so in ES5 (as per 8.6.2
in both ES3 and ES5-draft specs).


Host objects should not be passed to "isArray" functions of any
flavor. Most designs should not need a such a function anyway.
But I thought the problem were different global objects, each with its own
Array property.

Yes, but AUIU only Array objects created in child windows have "Object"
[[Class]] values (rather than "Array" ones). This is what "confuses"
Miller device.

I thought it was frames as well. Regardless, as it is not 100%, you
must fall back to "duck typing" for "Object" classes. This is why
such functions should be designed out of the system.
This seems awkward.

It's just as it seems.

[snip]
 
T

Thomas 'PointedEars' Lahn

kangax said:
Thomas said:
kangax said:
Thomas 'PointedEars' Lahn wrote:
kangax wrote:
Thomas 'PointedEars' Lahn wrote:
The local version of object.js (0.1.5a.2009062116) currently features
jsx.object.isMethod() which allows to pass an object reference plus an
arbitrary number of string arguments. This allows e.g. isMethod(Array,
"prototype", "slice", "call") and avoids repeated calls of isMethod().
This sounds useful. Another common need is to test multiple methods on
the same base object, so these two (i.e. your n-level `isMethod` and
`areMethods`) might cover most of the use cases:

[...]
areMethods(document, 'body', ['appendChild', 'removeChild']);
Conceptionally, I like this approach best. Not much overloading and very
flexible. However, an Array object reference (which requires a reliable
Array test¹) should only be allowed as last argument to avoid expensive
backtracking; or do you have an idea for that as well?
Yes, an array as last argument is what I had in mind. Allowing it as any
argument seems impractical and unnecessarily expensive (i.e.
backtracking cost which you mentioned).
ACK. Implemented and tested OK last night so:

for (var i = 1; i < len; i++)
{
var
p = arguments,
p_is_Array = (i === len - 1 && jsx.object.isArray(p)),
origP = p;

for (var j = (p_is_Array && origP.length || 1); j--;)
{
if (p_is_Array) p = origP[j];

t = typeof o[p];

// ...
}
}

Did I miss something?


Looks good. You could take `len - 1` out of the loop as well


Yes, but I don't think subtraction by 1 justifies introducing another variable.
as avoid resolving `jsx.object.isArray` over and over,

Will do (as done elsewhere). However, it would have to be v.isArray(...)
in any case, or extensive rewrites might be needed if I change how
jsx.object.isArray() gets to the jsx.object.isInstanceOf() that it calls.
[...]
¹ Regarding the cross-frame issue: what about a property referring
to the current Array object to be set and reset before/after call
as needed?
I suppose you're talking about so-called Miller device (i.e. comparing
value of [[Class]] to "Array").
Yes, I don't like that for its many assumptions.

There are not so many assumptions. It works as designed with native
objects in compliant implementations. Host objects are of course allowed
to implement any [[Class]] value in ES3, but not so in ES5 (as per 8.6.2
in both ES3 and ES5-draft specs).
[...]

Hmmm. I will review that discussion.
This seems awkward. If I have 2 arrays from different frames, I would
need to set proper `jsx.Array` reference before testing each one of
them. And what if I don't know which frame array was created in?

How couldn't you know? You are accessing it.
What if that frame was removed from the document and I don't have a
reference to its global `Array` property?

That's a good argument. Question remains if such an Array object would even
continue working, though.
As far as type converting host objects (not methods!), didn't we just
have a conversation about it where you said that it should be safe to do so?

[...]
<http://groups.google.com/group/comp.lang.javascript/msg/4df3cf9b5a7bd60f>

Or am I missing something?
Yes, I was talking about return values of standardized methods there.

I'm pretty sure we were talking about `lastChild`/`firstChild` as an
operand in `if`/`while` expression (when "emptying" element contents).

You're right. However, I would submit that there is still a difference
between a property of a host object that must strictly follow specification,
and a host-defined property of the global object or a property of a host
object, that does not strictly follows implementation (for historical reasons).
`lastChild` is specified to be of type Node (or should I say - its
return value is specified to implement Node interface, or `null`).
`document`, in its turn, is specified to be of type Document, which
inherits from Node. Therefore type conversion on `lastChild` and
`window.document` carries similar risk,

That might seem awkward at first, but the untested standalone `document' is
indeed riskier than the untested `window.document' (given `window' doesn't
fail, of course). Failed identifier resolution throws an exception
everywhere and always. There is also the remote possibility of a `document'
property in the scope chain that does not refer to a document object.
from what I can see (unless objects implementing exactly
Document interface would be the ones to throw, and not
those that implement Node only; but that would be just
plain silly)

It is not the value but the existence of the property that matters here.
[snip `tryThis`]
/* ... */

var isMethod = jsx.object.isMethod = jsx.object.areMethods = function(o, p) {
var len = arguments.length;
if (len < 1) return false;

Shouldn't return value be other than boolean, to indicate that something
went wrong and differentiate from cases when tested method isn't
recognized as "method"? (e.g. is "unknown").

A possibility; but what should it be? These days I would even consider
throwing exceptions instead (guarded with eval(), of course).
Why initialize these on every method invocation?

Pretty inefficient, I know. I'm working on it.
I wouldn't use `arguments.callee` if possible (to take advantage of
environments which optimize).

If the property should not be owned by another object, `arguments.callee' is
a necessity as long as there cannot be a unique identifier (for backwards
compatibility) and user-defined read-only properties everywhere are still on
the wish list. And I really like using function objects as containers for
function-related properties.


PointedEars
 
T

Thomas 'PointedEars' Lahn

David said:
[...]
Host objects should not be passed to "isArray" functions of any
flavor. Most designs should not need a such a function anyway.
From what I remember (per Richard's observations), it was
*cross-window issue*, not cross-frame one.
But I thought the problem were different global objects, each with its own
Array property.
Yes, but AUIU only Array objects created in child windows have "Object"
[[Class]] values (rather than "Array" ones). This is what "confuses"
Miller device.

I thought it was frames as well. Regardless, as it is not 100%, you
must fall back to "duck typing" for "Object" classes. This is why
such functions should be designed out of the system.

How do you propose to do that here? It needs to be tested whether the
argument is an Array object reference or not.


BTW, please learn to quote properly *always*. Your continued/repeated
failure to comply with that simple FAQ-supported request sets a pretty
bad example for this group, given that you do post valuable advice.
Even you can't be that busy.


PointedEars
 
T

Thomas 'PointedEars' Lahn

David said:
Thomas said:
David said:
Thomas 'PointedEars' Lahn wrote:
RobG wrote:
<FAQENTRY>
There has been frequent mention of the legendary "isHostMethod"
function in this group over the last 18 months or so in conjunction
with statements that "boolean type conversion is out" for testing host
method availability. While that may be so, trying to find the elusive
method in all the noise is pretty difficult.
I discovered this version posted by Thomas in February 2008[1]:
My JSdocâ„¢ says:
* @author
* (C) 2003-2009 Thomas Lahn &lt;[email protected]&gt;
Oh mercy. You wrote that comment.
Because it's true.

Sort of.

I won't debate that the version of 2003/2004 is less evolved than what I
have now (that would be pretty bad performance); but please, credit where
credit is due:

<http://bytes.com/groups/javascript/151754-when-window-location-url-executed>

(Google doesn't seem to have it anymore, or the search function is borken.)
That was certainly not isHostMethod as that is what I named my
function.

Yes, I have never seen the need to make a difference there and I still don't
see it. Apparently Peter started to doubt, too.
Yours did not have the bit about "unknown" types, which
were apparently my discovery (every time I bring them up it seems
nobody knows what I am talking about.)

I don't know whose discovery that was, but apparently you were the first to
mention it on Usenet:

It is based on isMethodType from years back.

How come that you missed isMethod() from years back although it has been
referred to at least in the JSdocâ„¢ of isMethodType() ever since?


PointedEars
 
D

David Mark

[...]
Host objects should not be passed to "isArray" functions of any
flavor.  Most designs should not need a such a function anyway.
From what I remember (per Richard's observations), it was
*cross-window issue*, not cross-frame one.
But I thought the problem were different global objects, each with its own
Array property.
Yes, but AUIU only Array objects created in child windows have "Object"
[[Class]] values (rather than "Array" ones). This is what "confuses"
Miller device.
I thought it was frames as well.  Regardless, as it is not 100%, you
must fall back to "duck typing" for "Object" classes.  This is why
such functions should be designed out of the system.

How do you propose to do that here?  It needs to be tested whether the
argument is an Array object reference or not.

Chuck the whole thing and redo anything that initially indicated a
need for it.
BTW, please learn to quote properly *always*.  Your continued/repeated
failure to comply with that simple FAQ-supported request sets a pretty
bad example for this group, given that you do post valuable advice.
Even you can't be that busy.

LOL. You have no idea.
 
D

David Mark

David said:
Thomas said:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
RobG wrote:
<FAQENTRY>
There has been frequent mention of the legendary "isHostMethod"
function in this group over the last 18 months or so in conjunction
with statements that "boolean type conversion is out" for testing host
method availability.  While that may be so, trying to find the elusive
method in all the noise is pretty difficult.
I discovered this version posted by Thomas in February 2008[1]:
My JSdoc™ says:
 * @author
 *   (C) 2003-2009  Thomas Lahn &lt;[email protected]&gt;
Oh mercy.  You wrote that comment.
Because it's true.

I won't debate that the version of 2003/2004 is less evolved than what I
have now (that would be pretty bad performance); but please, credit where
credit is due:

<http://bytes.com/groups/javascript/151754-when-window-location-url-ex...>

(Google doesn't seem to have it anymore, or the search function is borken..)

If you mean isMethodType, then yes. You fought tooth and nail when I
proposed isHostMethod, which is just a slight improvement.
Yes, I have never seen the need to make a difference there and I still don't
see it.  Apparently Peter started to doubt, too.

What are you talking about? We debated this to death. Unless you
wish to exclude ActiveX methods, which can pop up anywhere in IE and
throw exceptions, isHostMethod is the way to go. Nobody ever said
what exactly MS was doing behind the scenes with that stuff (that's
all speculation.) The point is that cross-browser scripting is part
science and part history.
I don't know whose discovery that was, but apparently you were the first to
mention it on Usenet:

<http://groups.google.com/group/comp.lang.javascript/msg/b34757abe55aa...>

Okay, but how can you not know what the difference is?
How come that you missed isMethod() from years back although it has been
referred to at least in the JSdoc™ of isMethodType() ever since?

Seems odd, but I'll take your word for it. I seem to remember you
arguing about passing a reference to isHostMethod. I see you have
written a sequel too. Looks like a good idea, but please don't call
it areHostMethods as that one exists. I'm not saying you called it
that, but I've seen several proposals lately and one had that name.
 
T

Thomas 'PointedEars' Lahn

David said:
Thomas said:
David said:
kangax wrote:
Thomas 'PointedEars' Lahn wrote:
kangax wrote:
[...]
Host objects should not be passed to "isArray" functions of any
flavor. Most designs should not need a such a function anyway.
From what I remember (per Richard's observations), it was
*cross-window issue*, not cross-frame one.
But I thought the problem were different global objects, each with its own
Array property.
Yes, but AUIU only Array objects created in child windows have "Object"
[[Class]] values (rather than "Array" ones). This is what "confuses"
Miller device.
I thought it was frames as well. Regardless, as it is not 100%, you
must fall back to "duck typing" for "Object" classes. This is why
such functions should be designed out of the system.
How do you propose to do that here? It needs to be tested whether the
argument is an Array object reference or not.

Chuck the whole thing and redo anything that initially indicated a
need for it.

Now that's a pretty useless reply. You owe me at least 15 seconds of my time.
LOL. You have no idea.

Then post when you are not busy. The overall quality of your replies might
even increase, and rest assured the world isn't going to end because of that
delay. BTDT.


PointedEars
 
D

David Mark

David said:
Thomas said:
David Mark wrote:
kangax wrote:
Thomas 'PointedEars' Lahn wrote:
kangax wrote:
[...]
Host objects should not be passed to "isArray" functions of any
flavor.  Most designs should not need a such a function anyway.
From what I remember (per Richard's observations), it was
*cross-window issue*, not cross-frame one.
But I thought the problem were different global objects, each with its own
Array property.
Yes, but AUIU only Array objects created in child windows have "Object"
[[Class]] values (rather than "Array" ones). This is what "confuses"
Miller device.
I thought it was frames as well.  Regardless, as it is not 100%, you
must fall back to "duck typing" for "Object" classes.  This is why
such functions should be designed out of the system.
How do you propose to do that here?  It needs to be tested whether the
argument is an Array object reference or not.
Chuck the whole thing and redo anything that initially indicated a
need for it.

Now that's a pretty useless reply.  You owe me at least 15 seconds of my time.

Look again. It's the only practical answer to your question.

[snip]
 
T

Thomas 'PointedEars' Lahn

David said:
Thomas said:
David said:
Thomas 'PointedEars' Lahn wrote:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
RobG wrote:
<FAQENTRY>
There has been frequent mention of the legendary "isHostMethod"
function in this group over the last 18 months or so in conjunction
with statements that "boolean type conversion is out" for testing host
method availability. While that may be so, trying to find the elusive
method in all the noise is pretty difficult.
I discovered this version posted by Thomas in February 2008[1]:
My JSdocâ„¢ says:
* @author
* (C) 2003-2009 Thomas Lahn &lt;[email protected]&gt;
Oh mercy. You wrote that comment.
Because it's true.
Sort of.
I won't debate that the version of 2003/2004 is less evolved than what I
have now (that would be pretty bad performance); but please, credit where
credit is due:

<http://bytes.com/groups/javascript/151754-when-window-location-url-ex...>

(Google doesn't seem to have it anymore, or the search function is borken..)

If you mean isMethodType, then yes.

You really can search for "function isMethod" there if you want. Trust me.
You fought tooth and nail when I proposed isHostMethod, which is just a
slight improvement.

Come on! I debated whether it would be useful in general to have a method
that requires another test before it can be used. And in part I still do,
hence my considering to allow identifier/member expression string evaluation
back (if via flag) after all. (I have already allowed a single argument for
isMethod() so that e.g. arguments of other methods could be tested without
isMethodType() and the "unknown" expression [the base object of the
reference would be the context's Variable Object, which is unavailable per
reference except global]. Turned out that you can't pass "unknown"s anyway.)
Yes, I have never seen the need to make a difference there and I still don't
see it. Apparently Peter started to doubt, too.

What are you talking about? [snip irrelevance]
I don't know whose discovery that was, but apparently you were the first to
mention it on Usenet:

<http://groups.google.com/group/comp.lang.javascript/msg/b34757abe55aa...>

Okay, but how can you not know what the difference is?

I don't follow.
Seems odd, but I'll take your word for it. I seem to remember you
arguing about passing a reference to isHostMethod. I see you have
written a sequel too. Looks like a good idea, but please don't call
it areHostMethods as that one exists.

It is going to be jsx.object.areMethods (and jsx.object.areHostMethods
should it prove to be needed), so there is only a remote possibility for
confusion.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top