summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/components/reps/rep.js
blob: 80d25b69e4cc463213075792167b037377c3526f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* -*- 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) {
  // Dependencies
  const React = require("devtools/client/shared/vendor/react");

  const { isGrip } = require("./rep-utils");

  // Load all existing rep templates
  const { Undefined } = require("./undefined");
  const { Null } = require("./null");
  const { StringRep } = require("./string");
  const { LongStringRep } = require("./long-string");
  const { Number } = require("./number");
  const { ArrayRep } = require("./array");
  const { Obj } = require("./object");
  const { SymbolRep } = require("./symbol");
  const { InfinityRep } = require("./infinity");
  const { NaNRep } = require("./nan");

  // DOM types (grips)
  const { Attribute } = require("./attribute");
  const { DateTime } = require("./date-time");
  const { Document } = require("./document");
  const { Event } = require("./event");
  const { Func } = require("./function");
  const { PromiseRep } = require("./promise");
  const { RegExp } = require("./regexp");
  const { StyleSheet } = require("./stylesheet");
  const { CommentNode } = require("./comment-node");
  const { ElementNode } = require("./element-node");
  const { TextNode } = require("./text-node");
  const { Window } = require("./window");
  const { ObjectWithText } = require("./object-with-text");
  const { ObjectWithURL } = require("./object-with-url");
  const { GripArray } = require("./grip-array");
  const { GripMap } = require("./grip-map");
  const { Grip } = require("./grip");

  // List of all registered template.
  // XXX there should be a way for extensions to register a new
  // or modify an existing rep.
  let reps = [
    RegExp,
    StyleSheet,
    Event,
    DateTime,
    CommentNode,
    ElementNode,
    TextNode,
    Attribute,
    LongStringRep,
    Func,
    PromiseRep,
    ArrayRep,
    Document,
    Window,
    ObjectWithText,
    ObjectWithURL,
    GripArray,
    GripMap,
    Grip,
    Undefined,
    Null,
    StringRep,
    Number,
    SymbolRep,
    InfinityRep,
    NaNRep,
  ];

  /**
   * Generic rep that is using for rendering native JS types or an object.
   * The right template used for rendering is picked automatically according
   * to the current value type. The value must be passed is as 'object'
   * property.
   */
  const Rep = React.createClass({
    displayName: "Rep",

    propTypes: {
      object: React.PropTypes.any,
      defaultRep: React.PropTypes.object,
      mode: React.PropTypes.string
    },

    render: function () {
      let rep = getRep(this.props.object, this.props.defaultRep);
      return rep(this.props);
    },
  });

  // Helpers

  /**
   * Return a rep object that is responsible for rendering given
   * object.
   *
   * @param object {Object} Object to be rendered in the UI. This
   * can be generic JS object as well as a grip (handle to a remote
   * debuggee object).
   *
   * @param defaultObject {React.Component} The default template
   * that should be used to render given object if none is found.
   */
  function getRep(object, defaultRep = Obj) {
    let type = typeof object;
    if (type == "object" && object instanceof String) {
      type = "string";
    } else if (object && type == "object" && object.type) {
      type = object.type;
    }

    if (isGrip(object)) {
      type = object.class;
    }

    for (let i = 0; i < reps.length; i++) {
      let rep = reps[i];
      try {
        // supportsObject could return weight (not only true/false
        // but a number), which would allow to priorities templates and
        // support better extensibility.
        if (rep.supportsObject(object, type)) {
          return React.createFactory(rep.rep);
        }
      } catch (err) {
        console.error(err);
      }
    }

    return React.createFactory(defaultRep.rep);
  }

  // Exports from this module
  exports.Rep = Rep;
});