summaryrefslogtreecommitdiff
path: root/posts/2021-01-28-undefined-javasript-is-undefined.php
diff options
context:
space:
mode:
author53hornet <atc@53hor.net>2021-07-28 10:58:58 -0400
committer53hornet <atc@53hor.net>2021-07-28 10:58:58 -0400
commitbfaccc32571df8a02f69518d8864244efba3b5b5 (patch)
treecc71a44054af00e73d0db2a1c79c347db3f31327 /posts/2021-01-28-undefined-javasript-is-undefined.php
parentdd75b4a341925e4ba3408b018941241d4317dd9f (diff)
download53hor-bfaccc32571df8a02f69518d8864244efba3b5b5.tar.xz
53hor-bfaccc32571df8a02f69518d8864244efba3b5b5.zip
php site, templating and partials, faster index generation
Diffstat (limited to 'posts/2021-01-28-undefined-javasript-is-undefined.php')
-rw-r--r--posts/2021-01-28-undefined-javasript-is-undefined.php108
1 files changed, 108 insertions, 0 deletions
diff --git a/posts/2021-01-28-undefined-javasript-is-undefined.php b/posts/2021-01-28-undefined-javasript-is-undefined.php
new file mode 100644
index 0000000..b70141c
--- /dev/null
+++ b/posts/2021-01-28-undefined-javasript-is-undefined.php
@@ -0,0 +1,108 @@
+<?php
+$title = "Undefined? JavaScript Is Undefined.";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ So I've been working on a web app for my mom. Nothing too fancy, but
+ it's a store front for her glass art. It's an easy way for her to keep
+ track of inventory, update photos of her products, and for people to
+ shop and search and sort and browse through it. This backend is an HTTP
+ service written in Rust. The frontend is a Vue.js app. I've used Vue and
+ JavaScript many times before but I recently ran into an incredibly
+ strange bug. One that I would have hoped JavaScript would have some
+ guard against. But JavaScript is an undefined language.
+</p>
+
+<p>
+ I have a small component that uses a file input to collect an image from
+ the user. Then I append that file to a FormData and set that FormData as
+ a Fetch API request body. So I've got fetch API sending
+ multipart/form-data across the network to my backend. Awesome! The
+ backend is supposed to take each field of the request, turn the chunks
+ into a single stream of binary data, and write them out to an image.
+ Everything on the front seems like it's working great, it fires off the
+ request and throws no errors. But then the backend only sees a few bytes
+ of this multi-megabyte image. Not awesome! short chunks on the back-end.
+ The array of data in the API is less than ten bytes long, when this is a
+ many-kilobyte file I'm trying to upload.
+</p>
+
+<p>
+ At this point I'm relentlessly debugging, trying to find out what's
+ wrong with the API. Why is it truncating the request down to a few
+ bytes, where's the rest of the data? It took me forever to actually
+ inspect what those few bytes are and, lo and behold they're ASCII for
+ <code>undefined</code> The request happily stringified an
+ <code>undefined</code> object, instead of maybe throwing a null
+ reference or undefined error during request creation because that's just
+ what JavaScript does. <em>The linter didn't even catch it.</em>
+</p>
+
+<p>
+ You can see what the debugging logs looked like on the backend below.
+ Note that the <code>&data</code> is the field that spells out
+ "undefined". Also note that the file picker/FormData was constructed
+ alright because the key for the image name is correct.
+</p>
+
+<pre>
+ <code>
+[src/handlers.rs:114] &field =
+Field: application/octet-stream
+ boundary: ---------------------------175314640631070190963311652907
+ headers:
+ "content-disposition": "form-data; name=\"clu.jpg\""
+
+[src/handlers.rs:119] &chunk = Ok(
+ b"undefined",
+)
+[src/handlers.rs:123] &data = [
+ 117,
+ 110,
+ 100,
+ 101,
+ 102,
+ 105,
+ 110,
+ 101,
+ 100,
+]
+ImageWrite("The image format could not be determined")
+ </code>
+ </pre>
+
+<p>
+ The <em>working</em> JS is here (it was late at night and I was so
+ donion rings I just fixed it and pushed it without saving the errors for
+ posterity):
+</p>
+
+<pre>
+ <code>
+let file = event.target.files[0];
+if (!file) {
+ return;
+}
+
+const fd = new FormData();
+fd.append(file.name, file);
+
+const response = await fetch("http://localhost:8000/photos", {
+ method: "POST",
+ body: fd
+});
+
+console.log(response);
+ </code>
+ </pre>
+<p>
+ I've gotten frustrated by JS before but not like this. I don't know if
+ TypeScript would have solved this issue but writing in a language that
+ gets transpiled back into the language I'm trying to avoid doesn't seem
+ like the way forward. I'm looking forward to Web Assembly as a way of
+ using more type-safe languages in the browser.
+</p>