Skip to content

JS - Don't use document.getElementsByName when updating some annotations #14008

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

Closed
wants to merge 1 commit into from

Conversation

calixteman
Copy link
Contributor

  - it aims to fix mozilla#14003.
  - in a custom viewer, the use of document.getElementsByName could lead to get some elements which don't correspond to an annotation, so this patch removes it and annotations with the same fieldName are collected when they're created.
@@ -2049,7 +2049,8 @@ class AnnotationLayer {
*/
static render(parameters) {
const sortedAnnotations = [],
popupAnnotations = [];
popupAnnotations = [],
sameName = new Map();
Copy link
Collaborator

@Snuffleupagus Snuffleupagus Sep 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could annotations with the same name ever be found on different pages, because if so I'm not sure that this will work (since it's limited to just the current page)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'd say that it was already an issue (I mean before this patch).

Copy link
Collaborator

@Snuffleupagus Snuffleupagus Sep 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My (possibly very stupid) idea when I initially saw the issue was that you could maybe track the created input elements in e.g. a WeakSet defined "globally" in this file, and then just check the elements that we lookup with document.getElementsByName against that.

Based on the following quote from #14003 (comment), Rob probably has better ideas though:

I suggest to replace the document.getElementsByTagName calls with a function that checks that the elements are created by the annotation_layer.js code before returning them. There are several ways to do so, e.g. by adding a custom attribute to each input element.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't avoid the problem with fields with same name across different pages: document.getElementsByName will get only the visible elements.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'd say that it was already an issue (I mean before this patch).

I see what you're saying, but it seems to me (I may be wrong of course) that it'd be slightly worse since before you got the Annotations on all active pages whereas with this patch it's only the current page.


Anyway, it seems that we might need to expand the AnnotationStorage to also have a name -> id mapping such that the initial value gets set correctly when rendering new pages? If so, that probably shouldn't be too hard to implement (famous last words).

This comment was marked as off-topic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I filed the issue I was thinking of something simple like using a WeakSet, tagging the element with a custom attribute, or even just prepending a prefix to the name to have something unique that can't overlap with existing ones. This draft patch looks more complex than that - why?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@calixteman Sorry if I'm massively overstepping here, but I've got a (possibly stupid) idea.

What if we utilized the data returned by the getFieldObjects-method in the API, since then we'd be able to both access the fields on all active pages and also update the AnnotationStorage for not-yet-rendered pages?

master...Snuffleupagus:AnnotationLayer-getElementsByName

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Snuffleupagus, no, you aren't and I think that's a very good idea.
This way we don't have to change AnnotationStorage implementation because we'll have all the ids for fields with the same name. Would you mind to write the patch since you've almost thought about everything here ? If yes, please close this one.

@Rob--W, my idea was to remove the call to getElementsByName and just update the fields with the same name. But as pointed out by Jonas, it was a bad idea and in the meantime it was not so bad because it helped us to find a bug.

@calixteman calixteman marked this pull request as draft September 12, 2021 18:40
@CetinSert
Copy link
Contributor

@calixteman – while eliminating document.getElementsByName, can we please consider

  • making the situation at least not worse for shadow DOM (Annotation layer in shadow DOM #13405)
  • or even better coming up with a solution that would work equally well for both light DOM and shadow DOM?

@Snuffleupagus pre-defense text

making the situation at least not worse for shadow DOM (#13405)

I know the use cases of Mozilla (with the viewer) but PDF.js as a library is very capable and generic (and able to power a lot more than just the whole document viewer it is bundled with) and document.getElementsByName is the only area in my usage that is not compatible with proper per-page encapsulation because of how it breaks form updates in such a setting.

@Snuffleupagus
Copy link
Collaborator

Re #14008 (comment), please let's not move the "goalpost" here since this PR is specifically about fixing issue #14003 and not something else (e.g. shadow DOM)?

@Snuffleupagus
Copy link
Collaborator

Closing in favour of PR #14023.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Hazard: annotation_layer.js uses document.getElementsByName without verification
4 participants