Account for typedef nullability (#257)

Account for typedef nullability

_desugarTypedef accepts a _RawType and returns its
underlying type if it's a typedef. However, it doesn't
account for whether the _RawType is nullable or not.
In order to accurately desugar a use of a typedef, we
should union the _RawType's nullability with the underlying
type's nullability. For example, `SomeTypedef?` should
always be nullable after being desugared.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d7e04d..b9cdd1a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@
   to avoid users accidentally downcasting `num`, which has different semantics
   depending on whether you compile to JS or Wasm. See issue [#57][] for more
   details.
+- Fix an issue where some union types didn't account for typedef nullability.
 
 [#57]: https://github.com/dart-lang/web/issues/57
 
diff --git a/lib/src/dom/webgl1.dart b/lib/src/dom/webgl1.dart
index bf50609..b6ef237 100644
--- a/lib/src/dom/webgl1.dart
+++ b/lib/src/dom/webgl1.dart
@@ -1630,7 +1630,7 @@
   /// buffer object's data store.
   external void bufferData(
     GLenum target,
-    JSAny dataOrSize,
+    JSAny? dataOrSize,
     GLenum usage,
   );
 
diff --git a/lib/src/dom/webgl2.dart b/lib/src/dom/webgl2.dart
index 68b354a..128ecfe 100644
--- a/lib/src/dom/webgl2.dart
+++ b/lib/src/dom/webgl2.dart
@@ -1268,7 +1268,7 @@
     GLint border,
     GLenum format,
     GLenum type,
-    JSAny pboOffsetOrSourceOrSrcData, [
+    JSAny? pboOffsetOrSourceOrSrcData, [
     int srcOffset,
   ]);
 
@@ -1287,7 +1287,7 @@
     GLsizei depth,
     GLenum format,
     GLenum type,
-    JSAny pboOffsetOrSourceOrSrcData, [
+    JSAny? pboOffsetOrSourceOrSrcData, [
     int srcOffset,
   ]);
 
@@ -1946,7 +1946,7 @@
   /// creates and initializes the buffer object's data store.
   external void bufferData(
     GLenum target,
-    JSAny sizeOrSrcData,
+    JSAny? sizeOrSrcData,
     GLenum usage, [
     int srcOffset,
     GLuint length,
@@ -1972,7 +1972,7 @@
     JSAny borderOrSource, [
     GLenum format,
     GLenum type,
-    JSAny pboOffsetOrPixelsOrSourceOrSrcData,
+    JSAny? pboOffsetOrPixelsOrSourceOrSrcData,
     int srcOffset,
   ]);
   external void texSubImage2D(
@@ -1984,7 +1984,7 @@
     JSAny heightOrType,
     JSAny formatOrSource, [
     GLenum type,
-    JSAny pboOffsetOrPixelsOrSourceOrSrcData,
+    JSAny? pboOffsetOrPixelsOrSourceOrSrcData,
     int srcOffset,
   ]);
   external void compressedTexImage2D(
@@ -2086,7 +2086,7 @@
     GLsizei height,
     GLenum format,
     GLenum type,
-    JSAny dstDataOrOffset, [
+    JSAny? dstDataOrOffset, [
     int dstOffset,
   ]);
   external JSObject get canvas;
diff --git a/tool/generator/translator.dart b/tool/generator/translator.dart
index 189fdfb..c28f0ad 100644
--- a/tool/generator/translator.dart
+++ b/tool/generator/translator.dart
@@ -104,20 +104,23 @@
 }
 
 /// If [rawType] corresponds to an IDL type that we declare as a typedef,
-/// desugars the typedef.
+/// desugars the typedef, accounting for nullability along the way.
 ///
 /// Otherwise, returns null.
 _RawType? _desugarTypedef(_RawType rawType) {
   final decl = Translator.instance!._typeToDeclaration[rawType.type];
   return switch (decl?.type) {
-    'typedef' => _getRawType((decl as idl.Typedef).idlType),
+    'typedef' => _getRawType((decl as idl.Typedef).idlType)
+      ..nullable |= rawType.nullable,
     // TODO(srujzs): If we ever add a generic JS function type, we should
     // maybe leverage that here so we have stronger type-checking of
     // callbacks.
-    'callback' || 'callback interface' => _RawType('JSFunction', false),
+    'callback' ||
+    'callback interface' =>
+      _RawType('JSFunction', rawType.nullable),
     // TODO(srujzs): Enums in the WebIDL are just strings, but we could make
     // them easier to work with on the Dart side.
-    'enum' => _RawType('JSString', false),
+    'enum' => _RawType('JSString', rawType.nullable),
     _ => null
   };
 }