Y
ytrewq
Should dynamic ("expando") properties be restricted to native and
user-defined objects? Or should host objects - such as references to
the browser or a plug-in or to the document and its elements - also
allow them?
Adding (and removing) object properties dynamically is an acceptable
and common practice in JavaScript, and greatly adds to the power and
character of the language. Essentially, an object in JavaScript can be
considered to be a collection of name-value pairs that define its
properties (including methods, as function-valued properties), and one
is usually free to add to this properties list at will.
Well, that is certainly the case for native (built-in) objects, such as
those of type Object, Number, String, Array, Date, etc; also for any
objects created from user-defined (programmer-defined) constructor
functions.
But I have never been certain if it was advisable, or even "legal", to
add properties to objects created by the host, such as the document
object or an HTML element or an XML node.
(Trivial example: document.myNewProp = 1234; )
Obviously, the actual host-supplied object - presumably, an instance of
a class written in C++ or Java or a similar statically, strongly typed,
compiled language - cannot have new properties, such as myNewProp,
added at run-time. But I have always understood - correct me if I am
wrong - that the JavaScript interpreter would automatically create a
second object, on the JavaScript side of the DOM interface, as a proxy.
That is, a JavaScript-language proxy object would map onto the
host-language class-based object. The new property ("myNewProp") would
be added only to that proxy object, as just another name/value pair,
and not to the host object, which would know nothing of the addition.
Well that is the mental image I had of the process behind the scenes.
Adding expando properties does seems fairly common practice, and I have
succeeded with this practice until now, but that does not prove much;
perhaps the host programs and/or JavaScript interpreters/engines have
just been too lax and accomodating.
The reason for this message is that my luck has finally run out, with
the Batik/Squiggle SVG viewer (which I believe runs the Mozilla Rhino
JavaScript engine, written in Java) and I am seeking a resolution of
the problem.
I had been developing some interactive, scripted SVG applications, and
had added extra data, in the form of expando properties, to some SVG
element objects (<rect> elements, for example), as a convenient way of
attaching metadata directly to them, rather than having to keep track
of separate JavaScript arrays or collections of data. This approach
worked in ASV3 and ASV6 (Adobe SVG viewer plug-ins, versions 3 and 6)
within both IE6 and Mozilla Firefox 1.0. (running on a Windows 2000 OS
PC) But not in Batik 1.5.
I have drastically simplified the example SVG file to the following
rather trivial test-case:
======================================================================================================
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1" width="100%"
height="100%" onload="init(evt)">
<script><![CDATA[
function init(evt) {
var doc = evt.target.ownerDocument;
var rct = doc.getElementById("rct1");
rct.newProp = 1234;
alert("rct.newProp=" + rct.newProp);
}
]]></script>
<rect id="rct1" width="200" height="100" style="fill:red" />
</svg>
======================================================================================================
This works as intended in the Adobe plug-in in IE6 and in Mozilla. But
in Batik/Squiggle I got this error message:
org.mozilla.javascript.EvaluatorException: Java class
"org.apache.batik.dom.svg.SVGOMRectElement"
has no public instance field or method named "newProp".
This suggests that the JavaScript interpreter is trying to add -
without any proper error trapping - the "newProp" property to the host
object (of Java class SVGOMRectElement, which implements the SVG DOM
SVGRectElement interface), instead of to a proxy object on the
JavaScript side of the SVGRectElement interface.
Is it reasonable to regard this as a bug, or unwarranted restriction,
on the part of Batik? Or is Batik merely holding firm to a standard
that states one should not try to add properties to script references
to host-created objects?
Although this example features an XML/SVG document, I feel that this
issue is one that applies to JavaScript in general, as JavaScript is
always used in a context of some sort (web browser, SVG viewer or
plugin, HTML or XML DOM, and so on) which exposes its own objects, at
least indirectly, to the scripting language.
user-defined objects? Or should host objects - such as references to
the browser or a plug-in or to the document and its elements - also
allow them?
Adding (and removing) object properties dynamically is an acceptable
and common practice in JavaScript, and greatly adds to the power and
character of the language. Essentially, an object in JavaScript can be
considered to be a collection of name-value pairs that define its
properties (including methods, as function-valued properties), and one
is usually free to add to this properties list at will.
Well, that is certainly the case for native (built-in) objects, such as
those of type Object, Number, String, Array, Date, etc; also for any
objects created from user-defined (programmer-defined) constructor
functions.
But I have never been certain if it was advisable, or even "legal", to
add properties to objects created by the host, such as the document
object or an HTML element or an XML node.
(Trivial example: document.myNewProp = 1234; )
Obviously, the actual host-supplied object - presumably, an instance of
a class written in C++ or Java or a similar statically, strongly typed,
compiled language - cannot have new properties, such as myNewProp,
added at run-time. But I have always understood - correct me if I am
wrong - that the JavaScript interpreter would automatically create a
second object, on the JavaScript side of the DOM interface, as a proxy.
That is, a JavaScript-language proxy object would map onto the
host-language class-based object. The new property ("myNewProp") would
be added only to that proxy object, as just another name/value pair,
and not to the host object, which would know nothing of the addition.
Well that is the mental image I had of the process behind the scenes.
Adding expando properties does seems fairly common practice, and I have
succeeded with this practice until now, but that does not prove much;
perhaps the host programs and/or JavaScript interpreters/engines have
just been too lax and accomodating.
The reason for this message is that my luck has finally run out, with
the Batik/Squiggle SVG viewer (which I believe runs the Mozilla Rhino
JavaScript engine, written in Java) and I am seeking a resolution of
the problem.
I had been developing some interactive, scripted SVG applications, and
had added extra data, in the form of expando properties, to some SVG
element objects (<rect> elements, for example), as a convenient way of
attaching metadata directly to them, rather than having to keep track
of separate JavaScript arrays or collections of data. This approach
worked in ASV3 and ASV6 (Adobe SVG viewer plug-ins, versions 3 and 6)
within both IE6 and Mozilla Firefox 1.0. (running on a Windows 2000 OS
PC) But not in Batik 1.5.
I have drastically simplified the example SVG file to the following
rather trivial test-case:
======================================================================================================
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1" width="100%"
height="100%" onload="init(evt)">
<script><![CDATA[
function init(evt) {
var doc = evt.target.ownerDocument;
var rct = doc.getElementById("rct1");
rct.newProp = 1234;
alert("rct.newProp=" + rct.newProp);
}
]]></script>
<rect id="rct1" width="200" height="100" style="fill:red" />
</svg>
======================================================================================================
This works as intended in the Adobe plug-in in IE6 and in Mozilla. But
in Batik/Squiggle I got this error message:
org.mozilla.javascript.EvaluatorException: Java class
"org.apache.batik.dom.svg.SVGOMRectElement"
has no public instance field or method named "newProp".
This suggests that the JavaScript interpreter is trying to add -
without any proper error trapping - the "newProp" property to the host
object (of Java class SVGOMRectElement, which implements the SVG DOM
SVGRectElement interface), instead of to a proxy object on the
JavaScript side of the SVGRectElement interface.
Is it reasonable to regard this as a bug, or unwarranted restriction,
on the part of Batik? Or is Batik merely holding firm to a standard
that states one should not try to add properties to script references
to host-created objects?
Although this example features an XML/SVG document, I feel that this
issue is one that applies to JavaScript in general, as JavaScript is
always used in a context of some sort (web browser, SVG viewer or
plugin, HTML or XML DOM, and so on) which exposes its own objects, at
least indirectly, to the scripting language.