summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/components/reps/object.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/components/reps/object.js')
-rw-r--r--devtools/client/shared/components/reps/object.js171
1 files changed, 171 insertions, 0 deletions
diff --git a/devtools/client/shared/components/reps/object.js b/devtools/client/shared/components/reps/object.js
new file mode 100644
index 000000000..ffb1d1525
--- /dev/null
+++ b/devtools/client/shared/components/reps/object.js
@@ -0,0 +1,171 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+// Make this available to both AMD and CJS environments
+define(function (require, exports, module) {
+ // Dependencies
+ const React = require("devtools/client/shared/vendor/react");
+ const { createFactories } = require("./rep-utils");
+ const { Caption } = createFactories(require("./caption"));
+ const { PropRep } = createFactories(require("./prop-rep"));
+ // Shortcuts
+ const { span } = React.DOM;
+ /**
+ * Renders an object. An object is represented by a list of its
+ * properties enclosed in curly brackets.
+ */
+ const Obj = React.createClass({
+ displayName: "Obj",
+
+ propTypes: {
+ object: React.PropTypes.object,
+ mode: React.PropTypes.string,
+ },
+
+ getTitle: function (object) {
+ let className = object && object.class ? object.class : "Object";
+ if (this.props.objectLink) {
+ return this.props.objectLink({
+ object: object
+ }, className);
+ }
+ return className;
+ },
+
+ safePropIterator: function (object, max) {
+ max = (typeof max === "undefined") ? 3 : max;
+ try {
+ return this.propIterator(object, max);
+ } catch (err) {
+ console.error(err);
+ }
+ return [];
+ },
+
+ propIterator: function (object, max) {
+ let isInterestingProp = (t, value) => {
+ // Do not pick objects, it could cause recursion.
+ return (t == "boolean" || t == "number" || (t == "string" && value));
+ };
+
+ // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=945377
+ if (Object.prototype.toString.call(object) === "[object Generator]") {
+ object = Object.getPrototypeOf(object);
+ }
+
+ // Object members with non-empty values are preferred since it gives the
+ // user a better overview of the object.
+ let props = this.getProps(object, max, isInterestingProp);
+
+ if (props.length <= max) {
+ // There are not enough props yet (or at least, not enough props to
+ // be able to know whether we should print "more…" or not).
+ // Let's display also empty members and functions.
+ props = props.concat(this.getProps(object, max, (t, value) => {
+ return !isInterestingProp(t, value);
+ }));
+ }
+
+ if (props.length > max) {
+ props.pop();
+ let objectLink = this.props.objectLink || span;
+
+ props.push(Caption({
+ object: objectLink({
+ object: object
+ }, (Object.keys(object).length - max) + " more…")
+ }));
+ } else if (props.length > 0) {
+ // Remove the last comma.
+ props[props.length - 1] = React.cloneElement(
+ props[props.length - 1], { delim: "" });
+ }
+
+ return props;
+ },
+
+ getProps: function (object, max, filter) {
+ let props = [];
+
+ max = max || 3;
+ if (!object) {
+ return props;
+ }
+
+ // Hardcode tiny mode to avoid recursive handling.
+ let mode = "tiny";
+
+ try {
+ for (let name in object) {
+ if (props.length > max) {
+ return props;
+ }
+
+ let value;
+ try {
+ value = object[name];
+ } catch (exc) {
+ continue;
+ }
+
+ let t = typeof value;
+ if (filter(t, value)) {
+ props.push(PropRep({
+ mode: mode,
+ name: name,
+ object: value,
+ equal: ": ",
+ delim: ", ",
+ }));
+ }
+ }
+ } catch (err) {
+ console.error(err);
+ }
+
+ return props;
+ },
+
+ render: function () {
+ let object = this.props.object;
+ let props = this.safePropIterator(object);
+ let objectLink = this.props.objectLink || span;
+
+ if (this.props.mode == "tiny" || !props.length) {
+ return (
+ span({className: "objectBox objectBox-object"},
+ objectLink({className: "objectTitle"}, this.getTitle(object))
+ )
+ );
+ }
+
+ return (
+ span({className: "objectBox objectBox-object"},
+ this.getTitle(object),
+ objectLink({
+ className: "objectLeftBrace",
+ object: object
+ }, " { "),
+ ...props,
+ objectLink({
+ className: "objectRightBrace",
+ object: object
+ }, " }")
+ )
+ );
+ },
+ });
+ function supportsObject(object, type) {
+ return true;
+ }
+
+ // Exports from this module
+ exports.Obj = {
+ rep: Obj,
+ supportsObject: supportsObject
+ };
+});