123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
- /* 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) {
- // ReactJS
- const React = require("devtools/client/shared/vendor/react");
- // Dependencies
- const { createFactories, isGrip } = require("./rep-utils");
- const { Caption } = createFactories(require("./caption"));
- const { PropRep } = createFactories(require("./prop-rep"));
- // Shortcuts
- const { span } = React.DOM;
- /**
- * Renders generic grip. Grip is client representation
- * of remote JS object and is used as an input object
- * for this rep component.
- */
- const GripRep = React.createClass({
- displayName: "Grip",
- propTypes: {
- object: React.PropTypes.object.isRequired,
- mode: React.PropTypes.string,
- isInterestingProp: React.PropTypes.func
- },
- getTitle: function (object) {
- if (this.props.objectLink) {
- return this.props.objectLink({
- object: object
- }, object.class);
- }
- return object.class || "Object";
- },
- 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) {
- if (object.preview && Object.keys(object.preview).includes("wrappedValue")) {
- const { Rep } = createFactories(require("./rep"));
- return [Rep({
- object: object.preview.wrappedValue,
- mode: this.props.mode || "tiny",
- defaultRep: Grip,
- })];
- }
- // Property filter. Show only interesting properties to the user.
- let isInterestingProp = this.props.isInterestingProp || ((type, value) => {
- return (
- type == "boolean" ||
- type == "number" ||
- (type == "string" && value.length != 0)
- );
- });
- let properties = object.preview
- ? object.preview.ownProperties
- : {};
- let propertiesLength = object.preview && object.preview.ownPropertiesLength
- ? object.preview.ownPropertiesLength
- : object.ownPropertyLength;
- if (object.preview && object.preview.safeGetterValues) {
- properties = Object.assign({}, properties, object.preview.safeGetterValues);
- propertiesLength += Object.keys(object.preview.safeGetterValues).length;
- }
- let indexes = this.getPropIndexes(properties, max, isInterestingProp);
- if (indexes.length < max && indexes.length < propertiesLength) {
- // There are not enough props yet. Then add uninteresting props to display them.
- indexes = indexes.concat(
- this.getPropIndexes(properties, max - indexes.length, (t, value, name) => {
- return !isInterestingProp(t, value, name);
- })
- );
- }
- const truncate = Object.keys(properties).length > max;
- let props = this.getProps(properties, indexes, truncate);
- if (truncate) {
- // There are some undisplayed props. Then display "more...".
- let objectLink = this.props.objectLink || span;
- props.push(Caption({
- object: objectLink({
- object: object
- }, `${object.ownPropertyLength - max} more…`)
- }));
- }
- return props;
- },
- /**
- * Get props ordered by index.
- *
- * @param {Object} properties Props object.
- * @param {Array} indexes Indexes of props.
- * @param {Boolean} truncate true if the grip will be truncated.
- * @return {Array} Props.
- */
- getProps: function (properties, indexes, truncate) {
- let props = [];
- // Make indexes ordered by ascending.
- indexes.sort(function (a, b) {
- return a - b;
- });
- indexes.forEach((i) => {
- let name = Object.keys(properties)[i];
- let value = this.getPropValue(properties[name]);
- props.push(PropRep(Object.assign({}, this.props, {
- mode: "tiny",
- name: name,
- object: value,
- equal: ": ",
- delim: i !== indexes.length - 1 || truncate ? ", " : "",
- defaultRep: Grip
- })));
- });
- return props;
- },
- /**
- * Get the indexes of props in the object.
- *
- * @param {Object} properties Props object.
- * @param {Number} max The maximum length of indexes array.
- * @param {Function} filter Filter the props you want.
- * @return {Array} Indexes of interesting props in the object.
- */
- getPropIndexes: function (properties, max, filter) {
- let indexes = [];
- try {
- let i = 0;
- for (let name in properties) {
- if (indexes.length >= max) {
- return indexes;
- }
- // Type is specified in grip's "class" field and for primitive
- // values use typeof.
- let value = this.getPropValue(properties[name]);
- let type = (value.class || typeof value);
- type = type.toLowerCase();
- if (filter(type, value, name)) {
- indexes.push(i);
- }
- i++;
- }
- } catch (err) {
- console.error(err);
- }
- return indexes;
- },
- /**
- * Get the actual value of a property.
- *
- * @param {Object} property
- * @return {Object} Value of the property.
- */
- getPropValue: function (property) {
- let value = property;
- if (typeof property === "object") {
- let keys = Object.keys(property);
- if (keys.includes("value")) {
- value = property.value;
- } else if (keys.includes("getterValue")) {
- value = property.getterValue;
- }
- }
- return value;
- },
- render: function () {
- let object = this.props.object;
- let props = this.safePropIterator(object,
- (this.props.mode == "long") ? 100 : 3);
- let objectLink = this.props.objectLink || span;
- if (this.props.mode == "tiny") {
- return (
- span({className: "objectBox objectBox-object"},
- this.getTitle(object),
- objectLink({
- className: "objectLeftBrace",
- object: object
- }, "")
- )
- );
- }
- return (
- span({className: "objectBox objectBox-object"},
- this.getTitle(object),
- objectLink({
- className: "objectLeftBrace",
- object: object
- }, " { "),
- ...props,
- objectLink({
- className: "objectRightBrace",
- object: object
- }, " }")
- )
- );
- },
- });
- // Registration
- function supportsObject(object, type) {
- if (!isGrip(object)) {
- return false;
- }
- return (object.preview && object.preview.ownProperties);
- }
- let Grip = {
- rep: GripRep,
- supportsObject: supportsObject
- };
- // Exports from this module
- exports.Grip = Grip;
- });
|