-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement the fn:generate-id function #641
Conversation
BundleMonFiles updated (2)
Total files change +197B +0.12% Final result: ✅ View report in BundleMon website ➡️ |
Thanks!!! The test failing with a static error is this one: <test-case name="generate-id-018">
<description>generate-id() applied to a sequence of element nodes in backwards-compatibility mode</description>
<created by="Michael Kay" on="2010-12-20"/>
<modified by="Michael Kay" on="2013-01-15" change="make dependency on XPath explicit"/>
<environment ref="auction"/>
<dependency type="spec" value="XP20+"/>
<dependency type="feature" value="xpath-1.0-compatibility"/>
<test>generate-id(//*) eq generate-id(/*)</test>
<result>
<assert-true/>
</result>
</test-case> Sure. XPath 1.0 compatibility mode is not something we implement. Or ever will if it is up to me. Lets ignore it. The others are stranger. I would expect them to work since they are just verifying all ids are distinct. Can you maybe look into that? |
@DrRataplan Thank you for looking at this! I wasn't sure if those xpath features were implemented (my xpath knowledge mostly stops at 2.0 😀 ). It turns out the counter wasn't properly being passed to some children. I believe I have corrected the issue. |
Looks like there are some type errors I need to fix... |
I just realized that this won't really work for my use case (an xslt processor) unless I allow the caller of an |
Is that because you need the result to be deterministic over multiple
calls? A weakmap on the module level should fit that, right? Otherwise,
something on DomFacade would not be too dirty...
…On Wed, 5 Jun 2024, 22:07 Erik Hetzner, ***@***.***> wrote:
I just realized that this won't really work for my use case (an xslt
processor) unless I allow the caller of an evaluateXpath function to pass
in a counter. I'll give that a shot...
—
Reply to this email directly, view it on GitHub
<#641 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABGKEJEEUL2BVD3BJWHOE2TZF5VWLAVCNFSM6AAAAABIR3SHFWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJQHA3DKMBZGI>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Yes, that's right... I think a DomFacade seems like the way to go. Thanks for the tip. |
src/expressions/DynamicContext.ts
Outdated
@@ -16,6 +16,8 @@ class DynamicContext { | |||
public contextItemIndex: number; | |||
public contextSequence: ISequence; | |||
public variableBindings: { [s: string]: () => ISequence }; | |||
public generateIdMap: WeakMap<Node, string>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you move this weakmap to the module level, as in, make it its own file like this:
const generateIdMap: WeakMap<Node,string> = new WeakMap();
export default generateIdMap;
and just directly talk to that in the generate-id function, circumventing the DynamicContext, you will get that stability over multiple calls. Because this is a weakMap I don't expect any memory downsides. I'd like this more than externalizing this state with a DomFacade. That would require other users of FontoXPath to do some upgrading on their side, whcih I'm trying to minimize.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me! I'll give this a shot. Thank you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I implemented the function using a module, but the WeakMap
is not working as I expected with nodes. It doesn't seem to be recognizing previous nodes. I'm trying to track this down, but I would have expected nodes to be equal across subsequent calls. See the failing test here https://github.com/FontoXML/fontoxpath/actions/runs/9475980881/job/26108159273?pr=641#step:6:100
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NodePointers. Forgot about them.
In XQuery (Update Facility) we are sometimes cloning nodes, a lot. When you wrap a large structure (like let $ele := <ele/> let $wrap := <wrap>{$ele}</wrap> return $wrap
) the <ele/>
in $ele
and the one in the $wrap
are not equal ($ele is $wrap/ele
is false). playground
Figuring out how to circumvent this. The nodeCompare
function compares node identity, so that's close. We might have to memoize the createPointer
function in DomFacade.ts here. That is the only place we make NodePointers. This way it can work over XQuery-made nodes as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to work for the tests I wrote. There are probably situations where it won't work:
import { NodePointer, TinyNode } from '../../domClone/Pointer';
import { ConcreteNode } from 'src/domFacade/ConcreteNode';
const generateIdMap: WeakMap<TinyNode | ConcreteNode, string> = new WeakMap();
let generateIdCounter = 0;
function generateId(ptr: NodePointer): string {
const node = ptr.node;
if (!generateIdMap.has(node)) {
generateIdMap.set(node, `id${++generateIdCounter}`);
}
return generateIdMap.get(node);
}
export default generateId;
1d0a956
to
5f71b5b
Compare
Simple implementation, but it seems to work.
5f71b5b
to
cf86458
Compare
I'm pretty happy with what I have here - what do you think? |
I think it looks great! I'll have to take a proper gander next week, if
that is OK, after Midsommar. Thanks again!
…On Wed, 19 Jun 2024, 19:55 Erik Hetzner, ***@***.***> wrote:
I'm pretty happy with what I have here - what do you think?
—
Reply to this email directly, view it on GitHub
<#641 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABGKEJFH4UGSUNTAPTB6QNDZIHAYZAVCNFSM6AAAAABIR3SHFWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNZZGI2DONBSGQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
No problem! Thank you. I just wanted to let you know it was ready for your review. Thanks for everything. |
Better support depends on FontoXML/fontoxpath#641
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Let's merge it!
) => { | ||
let node: NodePointer; | ||
if (!nodeValue) { | ||
if (!dynamicContext || !dynamicContext.contextItem) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could've used the contextItemAsFirstArgument
helper, that does this internally, but I'm fine either way.
And improve coverage
6bd71eb
to
2d9d9a5
Compare
Finally got around to those linting errors. Thanks again for the help! |
Since I'm no longer with Fonto I cannot release this. @bwrrp, can you hit the ship button somewhere after your holidays? |
Thank you @DrRataplan ! and best of luck with the new work. |
Sorry for the delay, just released 3.33.0 which includes this |
🙏 Thank you! |
https://www.w3.org/TR/xpath-functions-31/#func-generate-id
Simple implementation, but it seems to work.