Problem/Motivation
#2550717: [JS] Replace jQuery.cookie with JS-cookie and provide a BC layer switches us from jquery.cookie to js.cookie 2.
js.cookie 3.0.0-rc.0 was just released, so we should look into upgrading to that version once it is stable.
https://github.com/js-cookie/js-cookie/releases
Need to evaluate whether there are breaking API changes that would force us to wait unto Drupal 10 or not.
Major Changes
Summary: The recommended and safe way of using setting and getting cookies should remain the same across v2 and v3. The way that an implementation would override default behaviors has changed.
- 3.0.0-beta.0
- getJSON and JSON handling is changed. The change record for js-cookie has been updated with examples of how to do this.
- Setting the path is exposed in js-cookie API. This doesn't really affect us, but may make the shim easier to implement.
- Which characters that are encoded/decoded have changed. This may affect the return output from using Cookies directly rather than the shim, which already uses a converter to be backwards-compatible with jquery.cookie.
- 3.0.0-beta.1
- Changes how we can override the Cookies object. The jquery.cookie shim hides this implementation, but people using Cookies directly and wanting to override defaults will need to use the withAttributes factory method.
- Also, changing the options on an instantiation of Cookies is no longer possible. This mainly would affect the tests. We could mitigate risk by recommending creating new instances of the api.
- Converters will always need to take an object. Currently the shim does pass a function rather than an object with a read property, but that could easily be changed without affecting backwards-compatibility. We can mitigate risk by recommending that users not use the deprecated functionality in js-cookie v2 when using withConverter.
- Also, converters should call the default converter within their functions rather than relying on the internal mechanism to call it as that has been removed. Further comparison of how this works between v2 and v3 needs to be done.
- Creating an instance overriding both defaults and using converters would be a breaking change for implementations, but not for anyone using the jquery.cookie shim.
Proposed resolution
Remaining tasks
Review any API changes and document them.
Decide whether this should target 9.0.0, a minor release, or 10.0.0.
A patch updating to the beta for testing.
User interface changes
API changes
Data model changes
Release notes snippet
If updating from Drupal 9.0.0-beta1:
The core/js-cookie library (which was introduced in Drupal 9.0.0-beta1) has updated its js-cookie dependency from version 2.2.1 to version 3.0.0-rc.0. A summary of the differences in 2.2.1 and 3.0.0-rc.0 can be found by reviewing js-cookie's release history. Code that interacts with js-cookie via the shim provided by core/jquery.cookie is not impacted by this change.
If updating from any Drupal 9.x release other than beta1 or from any version of Drupal 8:
jquery.cookie has been replaced with js-cookie 3.0.0-rc.0. The core/js-cookie library is introduced, and a backwards-compatible shim is provided as core/jquery.cookie for Drupal 9.
Review the change record on js-cookie for more information.
| Comment | File | Size | Author |
|---|---|---|---|
| #41 | reroll_diff_41.txt | 7.45 KB | andyf |
| #41 | interdiff_35-41.txt | 889 bytes | andyf |
| #41 | 3118726-8.9.x-41.patch | 11.56 KB | andyf |
| #41 | 3118726-9.0.x-41.patch | 11.73 KB | andyf |
| #35 | 3118726-9.0.x-35.patch | 11.07 KB | jungle |
Comments
Comment #2
catchComment #3
xjmComment #4
lauriiiIt seems like a RC was released earlier today https://github.com/js-cookie/js-cookie/releases/tag/v3.0.0-rc.0
Comment #5
catchThis is unfortunate timing, although maybe better now than in a month.
Bumping to critical since it'll be critical for some version of Drupal core.
Comment #6
xjmWell, goldangit. This just bubbled to the top of the priority list.
This is a sort-of-beta-blocker-but-not-really-definitely-a-should-have to test with the RC.
We should also add to the release note from the jQuery Cookie issue to mention that we may be doing a major version update.
Comment #7
mradcliffeI did some analysis of this a few days ago. I revisited and updated the issue summary with the major changes.
I updated the change record of js-cookie a day or so ago to mention that it is not recommended to use getJSON() and provided the v3 methods which also work in v2.
The biggest changes will probably affect anyone using js-cookie for edge cases. Standard use of getting and setting cookies shouldn't matter with maybe an exception for how strings are encoded and decoded between versions.
One concern is that withAttributes and withConverter seem to be mutually-exclusive ways of creating an api instance. You can't both have a converter and change attributes. This might make the jquery.cookie shim a bit more complicated to implement because we needed to support backwards-compatibility for someone setting default options and trying to encode/decode the cookie values in the same way that jquery.cookie did so, which requires a converter. We could ask / file a feature request to allow this.
Comment #8
mradcliffeI think, on a second review, nesting calls should allow attributes and converters.
That should first create an instance to write to /some/ridiculous/path, and then create another instance with the converters.
That would still be a breaking change for anyone using js-cookie without the jquery.cookie shim, but the shim can encapsulate all of this.
Comment #9
mradcliffeWe could also recommend that contributed modules that want to do these edge cases write a wrapper of their own. This is described on Design Patterns to Use with JavaScript Cookie: Composition over inheritance. That would still mean a breaking change, but it could be dealt with by checking if Cookies.withAttributes is defined, and then use that pattern, or if it's not, use v2 pattern.
This could be a contrib module, and if there is no use case for setting cookies in core anymore, then jquery.cookie and js-cookie could both be removed in favor of a contrib module.
Comment #10
xjmComment #11
lauriiiI'm working on this
Comment #12
lauriiiI upgraded to js-cookie 3 and updated shim to make tests pass. There's one behavior change in js-cookie which I didn't figure out yet how to solve. In js-cookie 3, when all cookies are being retrieved, corrupted cookies are returned as undefined rather than being left out from the return payload.
Comment #13
xjmComment #14
bnjmnmThe issue in #12 may be due to this change in the new js-cookie
So get() should only be called with a variable if that variable is defined, otherwise it returns a bunch of nothing
Something like this ought to fix it:
Comment #15
phenaproximaThis will need a release note snippet before being committed.
Comment #16
bnjmnmIgnore #14 - that wasn't right.
I did some debugging and narrowed it down. I'm not sure why it's happening, but I'll document here and the answer may come to me if I step away for a bit.
The "Test jquery.cookie Shim Read all when there are cookies or return empty object" test passes locally but not on drupal's testbot (including the vagrant build I have on my machine).
The assertion that fails is checking the result of
getJqueryCookieI refactored
getJqueryCookieso it logged the return value before returning itgetJqueryCookiereturns the same value for both{\"js_cookie_test_first\":\"red panda\",\"js_cookie_test_second\":\"second red panda\"}"{\"js_cookie_test_first\":\"red panda\",\"js_cookie_test_second\":\"second red panda\"}"result.valueis different depending on env(the result gets js_cookie_test_third even though it isn't in the object returned by getJqueryCookie?)
At first glance it seems like the local test shouldn't be passing, but js_cookie_test_third manages to sneak its way into the results.
Comment #17
bnjmnmSome additional info:
I ran jsCookieTest using jquery.cookie instead of the shim. Since the goal of the shim is to reproduce the behavior of jquery.cookie, I wanted to confirm how it handled bad cookies.
The result returned by no-shim old-style jquery.cookie is
And fortunately this is consistent on drupalci and local. This return value differers from what is being tested for.
The patch adds for
js_cookie_test_third: undefinedto the object match, but it looks like jquery.cookie would not have returned this. This means that the patch, when run on drupalci, still matches the behavior of jquery.cookie - the test fails because it's looking for a third cookie that shouldn't be there.Not sure why
js_cookie_test_thirdmakes it through locally. At first glance it seems like theres a difference regarding how the return value is handled when the shim'sparseCookieValue ()hitscatch(e){}.While running jsCookieTest with jquery.cookie, I also encountered this failure
So something is out of sync here as well?
Comment #18
lauriiiThank you for debugging this! This is the line in jQuery cookie that ensured that cookies that couldn't be decoded aren't present in the object when all cookies are being retrieved: https://github.com/carhartl/jquery-cookie/blob/master/src/jquery.cookie..... Looking at js-cookie code, it doesn't seem like the behavior is the same: https://github.com/js-cookie/js-cookie/blob/master/src/api.mjs#L54. I'm still trying to figure out why #12 passed locally but failed on DrupalCI.
Comment #19
lauriiiDebugged the tests with @bnjmnm and we came with something that should solve #18, and pass both locally and on DrupalCI without making any changes to tests.
Comment #20
bnjmnmGoing through the code and release notes there appear to be three changes that needed to be addressed.
This is now taken care of in
reader()and is covered by existing testsThe use of
cookies.withConverterin the shim was factored accordinglyIs it necessary to iffe this?
The forEach can be shortened a bit like
Comment #21
lauriiiAddressed #20.3
Comment #22
bnjmnmPerhaps there's a better status to switch to. This is essentially an RTBC but can't be considered for commit until js-cookie 3 gets a full release - setting to postponed so there's no unnecessary additional work done on this. Unless something major changes between the RC and full, we'll just need a final patch that swaps in the full release.
Comment #23
xjm@catch, @effulgentsia, and I discussed this today and we think we'd actually prefer to depend on their RC than be stuck between an unsupported version and a major BC break during our RC or after. So, setting back to NR and we can RTBC it properly if that's correct. It still needs a release note and whatnot.
Comment #24
bnjmnmI was prepared to RTBC this in #22 had the full release been available. Now that it's decided we can use RC0, this is good to go. (having followed the Github activity in js-cookie for the past few months, I'm pretty comfortable with using rc0)
Added a release note snippet for updating from 9-beta1 and another for all other update situations.
Comment #25
xjmReviewing now!
Comment #26
xjmI attached https://www.drupal.org/node/3104677 to this issue. I think it needs to be updated?
Are there other CRs we need to update? Looking at #7.
Comment #27
xjmComment #28
bnjmnmI updated https://www.drupal.org/node/3104677 to reflect the change to v3, this included editing/removing several items specific to 2.x or the fact that 3.x was imminent.
Regarding the other CRs possibly needing updating question: I reviewed #7 and the similar comments following. This should not require any additional CR additions/changes. It was possible to adapt the shim to js-cookie 3.0.0-rc0 without having to compromise any functionality (comment #8 suspected this was possible...) . The shim being undisrupted is also confirmed by the fact that the (pretty thorough) test coverage did not have to change.
Comment #29
bnjmnm(rtbc since the CR is now updated)
Comment #30
xjmI tweaked the CR a bit to bring back the notes on differences between v2 and v3 (for anyone who tested the beta). Also adding a link to the CR for the release notes.
Comment #32
xjmAlright, reviewed all the changes here as well as all the comments. Looking good! I don't totally understand the test changes, but I understand why the were needed based on the issue discussion, and given both @bnjmnm and @lauriii were +1 on them (plus that, you know, they're passing) I'll go ahead and commit this.
We'll want to create a followup to update to 3.0.0 once it's released.
Saving issue credit...
Comment #33
xjmI tried to commit this and got a transpilation error on #21:
Did we forget to re-transpile after fixing the tests?
Comment #34
xjmWe also need to update the library in 8.9.x where we provide it for forward-compatibility. Will the same patch work for 8.9.x?
Comment #35
jungleLooks like forgetting to run build:js, a patch for 9.0.x
Comment #36
jungleFailed applying the patch in #35 to 8.9.x. I am not good at es6, so adding a needs reroll tag instead,
Comment #37
xjmVerified that #35 passes on the yarn build:
There are two ways we can indicate on an issue needs the patch backported. The best way is to set the branch to the lowest version needed. If the lower version's patch is not available at the time of commit, the committer will first commit it to the higher branches and then set the status to "Patch (to be ported)". We also sometimes use "Needs backport to X" issue tags, but the branch selector is preferable.
Thanks @jungle!
Comment #38
andyf commentedThanks all, here's a reroll for 8.9.
Comment #39
jungleRe #32, thanks @xjm!
Just FYI. The interdiff in #38 looks like one of the latest patches added unexpected leading space, or removed leading space, but checked the two patches on my local, nothing found.
Thanks!
Comment #40
bnjmnmFollowup created #3132164: Update to js-cookie 3.0.0 when it is released
The 9.x patch in #35 addresses the lack of transpiling.
The 8.x patch in #38 brings in the changes from the 9.x patch correctly. I suspect the spaces mentioned in #39 are due to how the interdiff was generated. It was against two patches vs. against core, which we are more accustomed to, but in this case was helpful to have been done this way.
However, I spotted something that needs to be changed in both patches. Both have two instances of
@see https://github.com/js-cookie/js-cookie/blob/v2.2.1/README.mdwhich references the README for the version being replaced. The contents of the respective readmes are significant enough that this should be updated to https://github.com/js-cookie/js-cookie/blob/v3.0.0-rc.0/README.mdComment #41
andyf commentedThanks @jungle for carefully looking over the reroll diff, they're always a pain to parse (:
Good spot @bnjmnm, thanks, fixed!
Comment #42
bnjmnm#40 addresses the last outstanding item, and I did an additional check of both patches to confirm they are correctly built/linted based on the differences in those tools in 8.x and 9.x
Comment #43
xjmComment #47
xjmAlright, I carefully reviewed the patches again and confirmed that the change record addresses the API changes for the new version (primarily an added parameter and related internal changes to the encoding functionality). I also compared the diffstats to ensure they're equivalent.
Committed the 9.0.x patch to 9.1.x and 9.0.x, and the 8.9.x patch to that branch. The CR is already published from the previous issue. Thanks!