blob: c1911846f207212ea0324254870c07a9ab0d5ed8 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2017 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.
-->
<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
<script>
'use strict';
tr.exportTo('tr.v.d', function() {
/**
* Stringify Arrays or dictionaries. Sorts dictionaries keys. Non-recursive.
*
* @param {!Object} obj
* @return {string}
*/
function stableStringify(obj) {
let replacer;
if (!(obj instanceof Array) && obj !== null) {
replacer = Object.keys(obj).sort();
}
return JSON.stringify(obj, replacer);
}
/**
* @typedef {(null|number|string|boolean|Array.<!PlainOldData>|!Object)}
* PlainOldData
*/
class GenericSet extends tr.v.d.Diagnostic {
/**
* @param {!Iterable.<!PlainOldData>} values
*/
constructor(values) {
super();
if (typeof values[Symbol.iterator] !== 'function') {
throw new Error('GenericSet must be constructed from an interable.');
}
this.values_ = new Set(values);
this.has_objects_ = false;
for (const value of values) {
if (typeof value === 'object') {
this.has_objects_ = true;
}
}
}
get size() {
return this.values_.size;
}
get length() {
return this.values_.size;
}
* [Symbol.iterator]() {
for (const value of this.values_) {
yield value;
}
}
has(value) {
if (typeof value !== 'object') return this.values_.has(value);
const json = JSON.stringify(value);
for (const x of this) {
if (typeof x !== 'object') continue;
if (json === JSON.stringify(x)) return true;
}
return false;
}
equals(other) {
if (!(other instanceof GenericSet)) return false;
if (this.size !== other.size) return false;
for (const value of this) {
if (!other.has(value)) return false;
}
return true;
}
get hashKey() {
if (this.has_objects_) return undefined;
if (this.hash_key_ !== undefined) {
return this.hash_key_;
}
let key = '';
for (const value of Array.from(this.values_.values()).sort()) {
key += value;
}
this.hash_key_ = key;
return key;
}
serialize(serializer) {
const i = [...this].map(x => serializer.getOrAllocateId(x));
return (i.length === 1) ? i[0] : i;
}
asDictInto_(d) {
d.values = Array.from(this);
}
static deserialize(data, deserializer) {
if (!(data instanceof Array)) {
data = [data];
}
return new GenericSet(data.map(datum => deserializer.getObject(datum)));
}
static fromDict(d) {
return new GenericSet(d.values);
}
clone() {
return new GenericSet(this.values_);
}
canAddDiagnostic(otherDiagnostic) {
return otherDiagnostic instanceof GenericSet;
}
addDiagnostic(otherDiagnostic) {
const jsons = new Set();
for (const value of this) {
if (typeof value !== 'object') continue;
jsons.add(stableStringify(value));
}
for (const value of otherDiagnostic) {
if (typeof value === 'object') {
if (jsons.has(stableStringify(value))) {
continue;
}
this.has_objects_ = true;
}
this.values_.add(value);
}
}
}
tr.v.d.Diagnostic.register(GenericSet, {
elementName: 'tr-v-ui-generic-set-span'
});
return {
GenericSet,
};
});
</script>