Reland "Apply trivial frontend defaults by copy, and recursively"

This is a (clean) reland of commit ba44daa08b94402e1d0ef4add3ff5c43fdd9c248

crbug.com/1516317 couldn't be fixed by clean revert so I will fix
it directly instead. This revert was only needed to attempt to clean revert another CL.

Original change's description:
> Apply trivial frontend defaults by copy, and recursively
>
> struct.WithTrivialFrontendDefaults() makes a member-by-member copy of
> the struct, applying defaults where needed and recursing where possible.
>
> Also adds a few missing static_asserts for `type.chained` structs.
>
> Bug: dawn:2224
> Change-Id: I5bb00d3c04f9417778114ffe79382266884208f7
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/168160
> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
> Reviewed-by: Loko Kung <lokokung@google.com>
> Auto-Submit: Kai Ninomiya <kainino@chromium.org>
> Kokoro: Kokoro <noreply+kokoro@google.com>
> Commit-Queue: Corentin Wallez <cwallez@chromium.org>

Bug: chromium:1516317
Bug: dawn:2224
Change-Id: I8e49dcec8f075deff351dccc624f40eaba990c4c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/168701
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Auto-Submit: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Austin Eng <enga@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index 078bb73..87d76ba 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -203,11 +203,6 @@
         self.default_value = default_value
         self.skip_serialize = skip_serialize
 
-        self.requires_struct_defaulting = False
-        if self.default_value not in [None, "undefined"] and self.annotation == "value" and \
-                self.type.category == "enum" and self.type.hasUndefined:
-            self.requires_struct_defaulting = True
-
     def set_handle_type(self, handle_type):
         assert self.type.dict_name == "ObjectHandle"
         self.handle_type = handle_type
@@ -216,6 +211,19 @@
         assert self.type.dict_name == "ObjectId"
         self.id_type = id_type
 
+    @property
+    def requires_struct_defaulting(self):
+        if self.annotation != "value":
+            return False
+
+        if self.type.category == "structure":
+            return self.type.any_member_requires_struct_defaulting
+        elif self.type.category == "enum":
+            return (self.type.hasUndefined
+                    and self.default_value not in [None, "undefined"])
+        else:
+            return False
+
 
 Method = namedtuple(
     'Method', ['name', 'return_type', 'arguments', 'autolock', 'json_data'])