-
-
Notifications
You must be signed in to change notification settings - Fork 637
fix(FormData): spec compliance #1501
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
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1501 +/- ##
=======================================
Coverage 94.83% 94.83%
=======================================
Files 50 50
Lines 4512 4513 +1
=======================================
+ Hits 4279 4280 +1
Misses 233 233
Continue to review full report at Codecov.
|
Surprisingly? 😄 |
Nothing else does the webidl conversions and FormData's doing all of them other than |
* fix(FormData): spec compliance * fix: remove erroneous check
I think there is an issue with the changes in the The first example of FormData usage on mozila does not work after this change
NodeJS: v18.6.0 |
Neither NodeJS or web worker have access to DOM, so what is really the problem? you can't construct a formdata with any arguments. thing it should still say |
i think perhaps the verdict is that "if you use jsdom" then you should also use jsdom formdata + jsdom fetch instead using undici components At least that was the jsdom authors arguments when i made a case with the Blob class as being incompatible with each other. it used more strict:er "instanceof OwnComponents" checks... and it stored the data on the blob that wasn't accessible without a jsdom FileReader. and they (still) lacks the new methods to read the blob with any of the promise-methods. ref: jsdom/jsdom#2555 I think (correct me if i'm wrong) that undici also accepts 3th party instances of FormData too (that aren't instances of undici's FormData) and they comply to the methods of iterating over it and reading each and every entry with iterators and being able to read files (as long as they have the newer read methods) |
Would you mind explaining how? I do not wish to use undici, but since Node released with it exposed in the global namespace by default it has just… replaced the other things. Can we stop that from happening somehow? I suppose this might be a test runner issue. It used to expose Is the intention that And for anyone else coming here from Google, I solved it on my case like this: import { JSDOM } from "jsdom";
const jsdom = JSDOM(`<!DOCTYPE html>`)
const FormData = jsdom.window.FormData;
export FormData; Then I could import this in my tests to shadow the globally defined |
i think jsdom should actually run in a own separated context like WebWorker instead with it's own sets of global variables |
The problem is when the implementation code uses Then you want to write a test for it that runs in a Node test runner. Node places its own constant on top that doesn't behave like the standard. Take this example: // feature.ts
export default function someExampleFeature(document: Document) {
document.addEventListener("submit", (event) => {
if (event.target instanceof HTMLFormElement) {
const form = event.target;
const data = new FormData(form);
if (data.has("message")) {
console.log("Form submitted with message:", data.get("message"));
} else {
console.log("Submitted a form without a message");
}
}
})
}
// app.ts
import someExampleFeature from "feature";
document.addEventListener("DOMContentLoaded", () => someExampleFeature(document)); Nothing here is strange (assuming I didn't make some unrelated mistake as I'm just typing this in a Github textarea after all). You'd have to work around it by adding code to allow injecting of "alternative" implementations of // feature.ts
+ export default function someExampleFeature(document: Document, formData?: any) {
+ const FormDataImpl = formData || FormData;
document.addEventListener("submit", (event) => {
if (event.target instanceof HTMLFormElement) {
const form = event.target;
+ const data = new FormDataImpl(form);
if (data.has("message")) {
console.log("Form submitted with message:", data.get("message"));
} else {
console.log("Submitted a form without a message");
}
}
})
} |
This should be made into an issue on the wintercg repo; is it better to allow a HTMLFormElement look alike or throw an error when an argument is passed to the constructor (current behavior in undici & deno)? |
in my point of view i mostly see Deno, cloudflare workers and NodeJS as some sort of web worker that don't have access to the DOM apis if anything then i think FormData should be acceptable of more or less the same arguments URLSearchParam dose with the added addition of blob support so that you can easily convert URLSearchParams & FormData back and forth it's easy to convert a html form to URLSearchParam and using FormData and convert it to a GET request with search params fetch(`/?${new URLSearchParams( new FormData( document.querySelector('form') ) )}`)
// but the revers is not easy for URLSearchParams back into a FormData
new FormData(new URLSearchParams({ foo: 'bar' })) // error not a HTMLFormElement If anything FormData should have been decoupled from any DOM api all together and don't have anything to do with it. since FormData can also live in Web Workers where the DOM is not accessible. const iterable = document.querySelector('form').values() // yields [string, string | File] for each element
new URLSearchParams( iterable )
new FormData( iterable )
new FormData({
foo: 'bar',
baz: new Blob()
})
new FormData([
['foo', 'bar'],
['baz', new Blob()],
['baz', new Blob()]
]) but it is easy to be a hindsight... |
* fix(FormData): spec compliance * fix: remove erroneous check
* fix(FormData): spec compliance * fix: remove erroneous check
makeEntry
since the spec was updated apparently.Surprisingly the
FormData
class was almost entirely correct and even did most of the webidl conversions.