blob: f4e94e97f3be98a840940a236444abde0033b542 [file] [log] [blame]
Victor Porof1a8a30d2022-06-13 13:07:10 +00001// Copyright 2022 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * Merges objects or arrays of objects. This is a simplistic merge operation
7 * that is only useful for generating the DOM pinned properties dataset.
8 *
9 * The merge happens in-place: b is merged *into* a.
10 * Both objects must be of the same type.
11 * Arrays are merged as unions with simple same-value-zero equality.
12 * Objects are merged with truthy-property precedence.
13 *
14 * @param {array|object} a
15 * @param {array|object} b
16 */
17export function merge(a, b) {
18 if (Array.isArray(a) && Array.isArray(b)) {
19 mergeArrays(a, b);
20 } else if (isNonNullObject(a) && isNonNullObject(b)) {
21 mergeObjects(a, b);
22 } else {
23 throw Error;
24 }
25
26 function isNonNullObject(value) {
27 return typeof value === 'object' && value !== null;
28 }
29
30 function mergeArrays(a, b) {
31 for (const value of b) {
32 if (!a.includes(value)) {
33 a.push(value);
34 }
35 }
36 }
37
38 function mergeObjects(a, b) {
39 for (const key of Object.keys(b)) {
40 if (isNonNullObject(a[key]) && isNonNullObject(b[key])) {
41 merge(a[key], b[key]);
42 } else {
43 a[key] = a[key] ?? b[key];
44 }
45 }
46 }
47}
48
49/**
50 * Finds "missing" types in a DOM pinned properties dataset.
51 * A "missing" type is defined as a type that is inherited or included by/in
52 * another type, but for which a definition wasn't found in the specs.
53 *
54 * This is a helper which helps to ensure that all relevant specs are parsed.
55 * E.g. some specs might reference types defined in other specs.
56 *
57 * @param {object} data
58 * @returns {array}
59 */
60export function getMissingTypes(data) {
61 const missing = new Set();
62 const keys = new Set(Object.keys(data));
63
64 for (const value of Object.values(data)) {
65 if (value.inherits) {
66 if (!keys.has(value.inherits)) {
67 missing.add(value.inherits);
68 }
69 }
70 if (value.includes) {
71 for (const include of value.includes) {
72 if (!keys.has(include)) {
73 missing.add(include);
74 }
75 }
76 }
77 }
78
79 return [...missing];
80}