The previous "fix" to always return copies for references to variables (i.e. for 'gVarRef', 'varRef', 'supplied') has been retracted. This was unnecessary (and slow) in various cases. New mechanisms are used to determine when to make copies of nodes.
Instead of labelling created nodes with _saxonIsTemporary (as in previous fix), we label with _saxonIsLocal, as outlined below.
Firstly, we now do more at compile time (Java code fixes on 9.7 and 9.8 branches). The ExpressionTool.isLocalConstructor() method is added to ask whether a supplied expression is a nested node constructor. This returns true if the child expression creates nodes that will only be used as children of some parent node (meaning that they do not need to be copied). The child expression (i.e. compElem, copy, doc, elem, comment, compAtt, att, namespace, procInst, valueOf) is then labelled with an "l" flag when isLocal() is true.
In Saxon-JS, when this flag is present, the created node is labelled with 'node._saxonIsLocal = true'.
We check for this label during the append method of Expr.makeComplexContent. If child._saxonIsLocal == true, then the child is "attachable", i.e. it may be possible to attach the child directly to the parent without needing a copy. A copy is made if the child is not attachable, or if the parent and child are not of the same type (i.e. both HTMLElements or both XML elements) - this ensures that constructed trees are homogeneous. Once attached to a parent, the child is no longer attachable, so we set child._saxonIsLocal = false.
Also made the fix for Mike's previous point: removed the use of DomUtils.shallowCopy when doing DomUtils.copyItem on an element.