Add a DOM pinned properties dataset generator
Signed-off-by: Victor Porof <victorporof@chromium.org>
Bug: 1325812
Change-Id: I292d49d273d74d33a82e25179478405395159537
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3695372
Reviewed-by: Mathias Bynens <mathias@chromium.org>
diff --git a/scripts/webidl-properties/util.js b/scripts/webidl-properties/util.js
new file mode 100644
index 0000000..f4e94e9
--- /dev/null
+++ b/scripts/webidl-properties/util.js
@@ -0,0 +1,80 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Merges objects or arrays of objects. This is a simplistic merge operation
+ * that is only useful for generating the DOM pinned properties dataset.
+ *
+ * The merge happens in-place: b is merged *into* a.
+ * Both objects must be of the same type.
+ * Arrays are merged as unions with simple same-value-zero equality.
+ * Objects are merged with truthy-property precedence.
+ *
+ * @param {array|object} a
+ * @param {array|object} b
+ */
+export function merge(a, b) {
+ if (Array.isArray(a) && Array.isArray(b)) {
+ mergeArrays(a, b);
+ } else if (isNonNullObject(a) && isNonNullObject(b)) {
+ mergeObjects(a, b);
+ } else {
+ throw Error;
+ }
+
+ function isNonNullObject(value) {
+ return typeof value === 'object' && value !== null;
+ }
+
+ function mergeArrays(a, b) {
+ for (const value of b) {
+ if (!a.includes(value)) {
+ a.push(value);
+ }
+ }
+ }
+
+ function mergeObjects(a, b) {
+ for (const key of Object.keys(b)) {
+ if (isNonNullObject(a[key]) && isNonNullObject(b[key])) {
+ merge(a[key], b[key]);
+ } else {
+ a[key] = a[key] ?? b[key];
+ }
+ }
+ }
+}
+
+/**
+ * Finds "missing" types in a DOM pinned properties dataset.
+ * A "missing" type is defined as a type that is inherited or included by/in
+ * another type, but for which a definition wasn't found in the specs.
+ *
+ * This is a helper which helps to ensure that all relevant specs are parsed.
+ * E.g. some specs might reference types defined in other specs.
+ *
+ * @param {object} data
+ * @returns {array}
+ */
+export function getMissingTypes(data) {
+ const missing = new Set();
+ const keys = new Set(Object.keys(data));
+
+ for (const value of Object.values(data)) {
+ if (value.inherits) {
+ if (!keys.has(value.inherits)) {
+ missing.add(value.inherits);
+ }
+ }
+ if (value.includes) {
+ for (const include of value.includes) {
+ if (!keys.has(include)) {
+ missing.add(include);
+ }
+ }
+ }
+ }
+
+ return [...missing];
+}