A kind reminder we would like all registered users to weigh in on one of our forum's security policies.
Please take a moment to read this thread and place a vote.
https://forum.palemoon.org/viewtopic.php?f=17&t=32935

Assigning text to a "value" property of a <textbox> element can broke it

Discussions about the development and maturation of the platform code (UXP).
Warning: may contain highly-technical topics.

Moderators: trava90, athenian200

User avatar
_yup_
Moonbather
Moonbather
Posts: 63
Joined: 2025-04-26, 11:45

Assigning text to a "value" property of a <textbox> element can broke it

Post by _yup_ » 2025-07-07, 20:32

There is something strange with programmatically added input elements, and I suppose this is a bug (and possibly more then one).

For examples below I use "Extension Developer" extension a playground.

A starting point with a static textbox control:

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">
        
<textbox id="textBox"/>
<label id="label"/>

<script>
<![CDATA[
var label = document.getElementById("label");
var textBox = document.getElementById("textBox");
textBox.value = "initial value";
]]>
</script>
</dialog>
Initial value is assigned to the .value property, can be edited by a user, and script code successfully reads user input:
1.png
Now I am adding the same element programmatically by document.createElement():

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">

<label id="label"/>

<script>
<![CDATA[
var label = document.getElementById("label");
var textBox = document.createElement("textbox");
label.before(textBox);
textBox.value = "initial value";
]]>
</script>

</dialog>
and it gets broken: initial value is not displayed to the user, and entered text does not affect the content of the .value property
2.png
And here I am using a static control again, but will remove it from the window before initializing and attach back after that:

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">
        
<textbox id="textBox"/>
<label id="label"/>

<script>
<![CDATA[
var label = document.getElementById("label");
var textBox = document.getElementById("textBox");
textBox.remove();
textBox.value = "initial value";
label.before(textBox);
]]>
</script>

</dialog>
The element appears broken:
3.png
One may decide that assigning a value to the off-screen textbox control broke it. But the reality is a little more complicated.

Apart from document.createElement(), there is .cloneNode() function. And using it I receive somewhat different results.
A clone works even after off-screen initialization:

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">
        
<textbox id="template"/>
<label id="label"/>

<script>
<![CDATA[
var label = document.getElementById("label");
var template = document.getElementById("template");
var textBox = template.cloneNode(false);
textBox.value = "old value";
label.after(textBox);
]]>
</script>
</dialog>
4.png
And even if a source element was removed before cloning, a clone remains usable:

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">
        
<textbox id="template"/>
<label id="label"/>

<script>
<![CDATA[
var label = document.getElementById("label");
var template = document.getElementById("template");
template.remove();
var textBox = template.cloneNode(false);
textBox.value = "old value";
label.after(textBox);
]]>
</script>

</dialog>
5.png
Moreover, even if a clone was made from a programmatically created off-screen element and was initialized remaining off-screen, it works as well:

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">
        
<label id="label"/>

<script>
<![CDATA[
var label = document.getElementById("label");
var template = document.createElement("textbox");
var textBox = template.cloneNode(false);
textBox.value = "old value";
label.after(textBox);
]]>
</script>

</dialog>
6.png
But again: the things are a bit more complicated.
If I clone not a single element, but a DOM tree of nested elements (that's the point of .cloneNode(true)), then textbox does not work been initialized either off-screen:

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">
        
<vbox id="template">
  <textbox />
</vbox>

<script>
<![CDATA[
var template = document.getElementById("template");
var clone = template.cloneNode(true);
var textBox = clone.getElementsByTagName("textbox")[0];
textBox.value = "old value";
template.after(clone);
]]>
</script>

</dialog>
7.png
or on-screen:

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">
        
<vbox id="template">
  <textbox />
</vbox>

<script>
<![CDATA[
var template = document.getElementById("template");
var clone = template.cloneNode(true);
var textBox = clone.getElementsByTagName("textbox")[0];
template.after(clone);
textBox.value = "old value";
]]>
</script>

</dialog>
8.png
(I have not looked at other input controls yet.)
You do not have the required permissions to view the files attached to this post.

User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 38514
Joined: 2011-08-28, 17:27
Location: Sweden

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Moonchild » 2025-07-07, 21:45

I don't think you're handling the XUL hierarchy correctly.
IIRC, just using .before isn't doing what you expect.
You may want to reference https://udn.realityripple.com/docs/Web/API/Node/insertBefore -- inserting a sibling is a little more involved since you have to reference the parent node. As a result I think the added element will be a childNode and not a sibling, so your references to manipulate the value would then be wrong.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite

User avatar
_yup_
Moonbather
Moonbather
Posts: 63
Joined: 2025-04-26, 11:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by _yup_ » 2025-07-07, 22:05

Moonchild wrote:
2025-07-07, 21:45
just using .before isn't doing what you expect.
While creating the starting post, I tried to use a surrounding <groupbox> and .appendChild() to it.
The result was the same.
Moonchild wrote:
2025-07-07, 21:45
As a result I think the added element will be a childNode and not a sibling, so your references to manipulate the value would then be wrong.
I am manipulating the value of an element that I created - by using the return value of createElement()/cloneNode(), and not of getElementsBy...(). So the result can not depend on where exactly this element was inserted. Especially in those cases, where I modified the .value before adding the element to the DOM.

User avatar
_yup_
Moonbather
Moonbather
Posts: 63
Joined: 2025-04-26, 11:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by _yup_ » 2025-07-07, 22:33

This is an example with <groupbox>:

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" ?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); return false;">
        
<groupbox id="groupbox">
  <vbox id="template">
    <textbox />
  </vbox>
</groupbox>

<script>
<![CDATA[
var groupbox = document.getElementById("groupbox");
var template = document.getElementById("template");
var clone = template.cloneNode(true);
var textBox = clone.getElementsByTagName("textbox")[0];
groupbox.appendChild(clone);
textBox.value = "initial value";
]]>
</script>

</dialog>

User avatar
moonbat
Knows the dark side
Knows the dark side
Posts: 5720
Joined: 2015-12-09, 15:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by moonbat » 2025-07-07, 23:44

In my view it's best not to use DOM manipulation to create the UI when XUL exists. In fact don't even mix XUL and Javascript. You can assign the script to the XUL file using the script tag and then reference all XUL elements within it by name, and set the script to load when the window loads. Strict separation between UI and control logic.
Unless you're dynamically adding elements to the UI at runtime there is zero need to createElement or createNode.
"One hosts to look them up, one DNS to find them and in the darkness BIND them."

Image
KDE Neon on a Slimbook Excalibur (Ryzen 7 8845HS, 64 GB RAM)
AutoPageColor|PermissionsPlus|PMPlayer|Pure URL|RecordRewind|TextFX
Jabber: moonbat@hot-chili.net

User avatar
_yup_
Moonbather
Moonbather
Posts: 63
Joined: 2025-04-26, 11:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by _yup_ » 2025-07-08, 00:43

moonbat wrote:
2025-07-07, 23:44
You can assign the script to the XUL file using the script tag and then reference all XUL elements within it by name, and set the script to load when the window loads.
I agree. But initially I discovered this problem when was working on the "Search Engine Editor" extension, and it is structured exactly as you have described.
In examples above everything is placed into one file just for simplicity.
moonbat wrote:
2025-07-07, 23:44
Unless you're dynamically adding elements to the UI at runtime there is zero need to createElement or createNode.
Below is a fragment of EngineEditor.xul, which the handler of its "load" event (resided in EngineEditor.js) have to duplicate unpredictable number of times, because it is not known beforehand how many these panels the window must contain.

Code: Select all

<tabpanel orient="vertical">
  <hbox align="center">
    <label value="&URL.label;"/>
    <textbox role="URL" flex="1"/>
    <label value="&method.label;"/>
    <menulist role="method">
      <menupopup>
        <menuitem label="GET"/>
        <menuitem label="POST"/>
      </menupopup>
    </menulist>
  </hbox>

  <hbox align="center">
    <label value="&resultDomain.label;"/>
    <textbox role="resultDomain" flex="1"/>
    <label value="&rels.label;"/>
    <textbox role="rels" flex="1"/>
  </hbox>

  <tree role="params" flex="1" editable="true" seltype="single" hidecolumnpicker="true">
    <treecols>
      <treecol label="&param.label;" flex="0"/>
      <splitter class="tree-splitter" resizeafter="closest"/>
      <treecol label="&value.label;" flex="1"/>
    </treecols>
    <treechildren/>
  </tree>
</tabpanel>
This is why the browser provides cloneNode() function.
Last edited by _yup_ on 2025-07-08, 07:01, edited 1 time in total.

User avatar
moonbat
Knows the dark side
Knows the dark side
Posts: 5720
Joined: 2015-12-09, 15:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by moonbat » 2025-07-08, 04:28

_yup_ wrote:
2025-07-08, 00:43
This is why the browser provides cloneNode() function.
Understood, this is the sort of situation I meant where one is dynamically adding UI elements.
"One hosts to look them up, one DNS to find them and in the darkness BIND them."

Image
KDE Neon on a Slimbook Excalibur (Ryzen 7 8845HS, 64 GB RAM)
AutoPageColor|PermissionsPlus|PMPlayer|Pure URL|RecordRewind|TextFX
Jabber: moonbat@hot-chili.net

User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 38514
Joined: 2011-08-28, 17:27
Location: Sweden

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Moonchild » 2025-07-08, 07:07

Keep in mind that Web APIs not always apply to XUL in the same way. e.g. by default you can't use html elements that the browser supports in content. Namespaces are different and not all bindings necessarily work the same way. I don't even know what the situation is exactly with in-lining js with <![CDATA[ -- moonbat makes a good point about having js separate. i.e.: I'm not so sure this is a bug, per se, and more a design decision (e.g. for chrome-sec reasons).
I'm not sure why you want to manipulate the XUL tree in-place to begin with. Just separate out the XUL UI elements as UI structure in .xul, any scripting into .js, and treat it as a more traditional trio of XML/JS/CSS than trying to do DOM jiggery-pokery to manipulate the elements.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite

User avatar
_yup_
Moonbather
Moonbather
Posts: 63
Joined: 2025-04-26, 11:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by _yup_ » 2025-07-08, 08:33

Moonchild wrote:
2025-07-08, 07:07
Keep in mind that Web APIs not always apply to XUL in the same way. e.g. by default you can't use html elements that the browser supports in content.
In examples above I use either createElement(), or cloneNode(). Both functions are described in Web API section, but also both are equally mentioned in XUL documentation: - explicitly and without any precautions.

textbox specification also does not impose any restrictions on manipulation with .value:
value
Type: string
Holds the current value of the textbox as a string. The current value may be modified by setting this property.
Moonchild wrote:
2025-07-08, 07:07
I'm not sure why you want to manipulate the XUL tree in-place to begin with. Just separate out the XUL UI elements as UI structure in .xul, any scripting into .js, and treat it as a more traditional trio of XML/JS/CSS than trying to do DOM jiggery-pokery to manipulate the elements.
As I answered to moonbat, the problem initially was observed in a real code, where everything (XUL/JS/CSS) was in separate files.
Moonchild wrote:
2025-07-08, 07:07
i.e.: I'm not so sure this is a bug, per se, and more a design decision (e.g. for chrome-sec reasons).
I suppose a bug due to impermanence of phenomena.

User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 38514
Joined: 2011-08-28, 17:27
Location: Sweden

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Moonchild » 2025-07-08, 08:44

_yup_ wrote:
2025-07-08, 08:33
explicitly and without any precautions.
in web content.

MDN Web APIs only applies to web content. It may or may not apply the same way to XUL.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite

User avatar
_yup_
Moonbather
Moonbather
Posts: 63
Joined: 2025-04-26, 11:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by _yup_ » 2025-07-08, 10:03

Those quotes were from a "Modifying a XUL Interface" (http://udn.realityripple.com/docs/Archive/Mozilla/XUL/Tutorial/Modifying_a_XUL_Interface) article, published by Mozilla.

For me this means that using of mentioned functions for XUL elements is officially approved.

User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 38514
Joined: 2011-08-28, 17:27
Location: Sweden

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Moonchild » 2025-07-08, 10:36

Yes, the methods may be "sanctioned", but you may run into nuance differences.

But, if you feel it's an actual bug then please file an issue on the tracker, and if you want to help improve, find the bugzilla bug that fixed it (assuming Mozilla fixed it); e.g. using mozregression.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite

User avatar
Nuck-TH
Project Contributor
Project Contributor
Posts: 323
Joined: 2020-03-02, 16:04

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Nuck-TH » 2025-07-08, 12:21

If there is need to contextually show different controls at the same place, i think better approach would be have them all defined in XUL, but all hidden except default set, and then showing/hiding them as needed instead of document tree manipulation.

User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 38514
Joined: 2011-08-28, 17:27
Location: Sweden

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Moonchild » 2025-07-08, 12:58

Nuck-TH wrote:
2025-07-08, 12:21
If there is need to contextually show different controls at the same place, i think better approach would be have them all defined in XUL, but all hidden except default set, and then showing/hiding them as needed instead of document tree manipulation.
This is the normal way of doing it. e.g. tabbed interfaces just disable/hide the tabs (and tab contents) not active but they are all in the UI at the same time.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite

Kris_88
Board Warrior
Board Warrior
Posts: 1168
Joined: 2021-01-26, 11:18

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Kris_88 » 2025-07-08, 13:54

Try this:

Code: Select all

<?xml version="1.0"?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept"
        ondialogaccept="alert(textBox.value); textBox.value='updated 123'; return false;">

<label id="label"/>

<script>
<![CDATA[
var label = document.getElementById("label");
var textBox = document.createElement("textbox");
var de = document.documentElement;
de.appendChild(textBox);

// The property "value" seems to be missing at the moment
// or the setter has not been assigned yet.
// Assigning will create the property, but it will not work any further
// (i.e. it will not be related to the state of the textbox).
// Use setAttribute here.

textBox.setAttribute('value', "initial value abc");

]]>
</script>

</dialog>


Kris_88
Board Warrior
Board Warrior
Posts: 1168
Joined: 2021-01-26, 11:18

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Kris_88 » 2025-07-08, 21:40

The problem is probably that the dialog hasn't fully initialized yet while your script is running.
Here it is - it works as it should if you create the element during the "load" event:

Code: Select all

<script>
<![CDATA[

var textBox;

window.addEventListener("load", function(e) { 

  textBox = document.createElement("textbox");
  document.documentElement.appendChild(textBox);
  textBox.value = "initial value abc";

}, false);

]]>
</script>

User avatar
_yup_
Moonbather
Moonbather
Posts: 63
Joined: 2025-04-26, 11:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by _yup_ » 2025-07-08, 21:54

This your example works not because the code is executed in the "load" event handler, but because it changes the .value after attaching the element to a DOM tree. (Let try the opposite order.)

Today i put some efforts, studying the sources and tracing in the debugger, so I already understand what happens, when and why. I only need a time to issue the post.

Kris_88
Board Warrior
Board Warrior
Posts: 1168
Joined: 2021-01-26, 11:18

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Kris_88 » 2025-07-08, 22:10

_yup_ wrote:
2025-07-08, 21:54
, but because it changes the .value after attaching the element to a DOM tree.
In your script you do the same, but it doesn't work:

Code: Select all

<script>
<![CDATA[
var label = document.getElementById("label");
var textBox = document.createElement("textbox");
label.before(textBox);
textBox.value = "initial value";
]]>
</script>
And if you do it this way, it works.

Code: Select all

<script>
<![CDATA[
var textBox;
window.addEventListener("load", function(e) { 
  var label = document.getElementById("label");
  textBox = document.createElement("textbox");
  label.before(textBox);
  textBox.value = "initial value";
}, false);
]]>
</script>

User avatar
_yup_
Moonbather
Moonbather
Posts: 63
Joined: 2025-04-26, 11:45

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by _yup_ » 2025-07-08, 22:20

addEventListener() is only a part of the solution. Attaching the element to a DOM tree before setting the .value is a second part.

(I see what can be changed in the XBL bindings file to overcome all these hassles. Just two additional lines of code.)

Kris_88
Board Warrior
Board Warrior
Posts: 1168
Joined: 2021-01-26, 11:18

Re: Assigning text to a "value" property of a <textbox> element can broke it

Post by Kris_88 » 2025-07-08, 23:20

_yup_ wrote:
2025-07-08, 22:20
(I see what can be changed in the XBL bindings file to overcome all these hassles. Just two additional lines of code.)
Anyway, using setAttribute it works too. And you don't need to use events and you can set the initial value before adding the element to the DOM. So for those who don't want to wait... :

Code: Select all

<script>
<![CDATA[
var label = document.getElementById("label");
var textBox = document.createElement("textbox");
textBox.setAttribute('value', "initial value");

label.before(textBox);
]]>
</script>