Bug 1219304 - add react-dom and use it in the devtools to render react r=jsantell, a=blanket-sylvestre
authorJames Long <longster@gmail.com>
Sat, 31 Oct 2015 16:23:30 -0700
changeset 305350 b03b4145b89e7c641ff38d0d4870d0e7ff91b120
parent 305349 7063e8c719a2d48e4fb5024f7a0a6c8501d1eabb
child 305351 d02de1b2320dfb3ff45b80d5e5620011a10d375c
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjsantell, blanket-sylvestre
bugs1219304
milestone44.0a2
Bug 1219304 - add react-dom and use it in the devtools to render react r=jsantell, a=blanket-sylvestre --HG-- extra : amend_source : 4aa25a00c9e1a0a51fbc7b08d4c8fb15393f83e2
devtools/client/jsonview/json-viewer.js
devtools/client/jsonview/viewer-config.js
devtools/client/memory/components/test/mochitest/test_tree_01.html
devtools/client/memory/components/test/mochitest/test_tree_02.html
devtools/client/memory/components/test/mochitest/test_tree_03.html
devtools/client/memory/components/test/mochitest/test_tree_04.html
devtools/client/memory/components/test/mochitest/test_tree_05.html
devtools/client/memory/components/test/mochitest/test_tree_06.html
devtools/client/memory/components/test/mochitest/test_tree_07.html
devtools/client/memory/components/test/mochitest/test_tree_08.html
devtools/client/memory/initializer.js
devtools/client/shared/vendor/REACT_UPGRADING
devtools/client/shared/vendor/moz.build
devtools/client/shared/vendor/react-dom.js
--- a/devtools/client/jsonview/json-viewer.js
+++ b/devtools/client/jsonview/json-viewer.js
@@ -2,17 +2,17 @@
 /* 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/. */
 
 define(function(require, exports, module) {
 
 // ReactJS
-const React = require("react");
+const ReactDOM = require("react-dom");
 
 // RDP Inspector
 const { createFactories } = require("./components/reps/rep-utils");
 const { MainTabbedArea } = createFactories(require("./components/main-tabbed-area"));
 
 const json = document.getElementById("json");
 const headers = document.getElementById("headers");
 
@@ -74,17 +74,17 @@ input.actions = {
   },
 }
 
 /**
  * Render the main application component. It's the main tab bar displayed
  * at the top of the window. This component also represents ReacJS root.
  */
 var content = document.getElementById("content");
-var theApp = React.render(MainTabbedArea(input), content);
+var theApp = ReactDOM.render(MainTabbedArea(input), content);
 
 var onResize = event => {
   window.document.body.style.height = window.innerHeight + "px";
   window.document.body.style.width = window.innerWidth + "px";
 }
 
 window.addEventListener("resize", onResize);
 onResize();
--- a/devtools/client/jsonview/viewer-config.js
+++ b/devtools/client/jsonview/viewer-config.js
@@ -18,14 +18,15 @@
  * See also: http://requirejs.org/docs/api.html#pathsfallbacks
  */
 require.config({
   baseUrl: ".",
   paths: {
     "react": [
       "resource://devtools/client/shared/vendor/react-dev",
       "resource://devtools/client/shared/vendor/react"
-    ]
+    ],
+    "react-dom": "resource://devtools/client/shared/vendor/react-dom"
   }
 });
 
 // Load the main panel module
 requirejs(["json-viewer"]);
--- a/devtools/client/memory/components/test/mochitest/test_tree_01.html
+++ b/devtools/client/memory/components/test/mochitest/test_tree_01.html
@@ -11,26 +11,27 @@ depth.
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <pre id="test">
 <script src="head.js" type="application/javascript;version=1.8"></script>
 <script type="application/javascript;version=1.8">
 window.onload = Task.async(function* () {
   try {
+    let ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
     let React = bRequire("devtools/client/shared/vendor/react");
     let Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
 
     ok(React, "Should get React");
     ok(Tree, "Should get Tree");
 
     const t = Tree(TEST_TREE_INTERFACE);
     ok(t, "Should be able to create Tree instances");
 
-    const tree = React.render(t, window.document.body);
+    const tree = ReactDOM.render(t, window.document.body);
     ok(tree, "Should be able to mount Tree instances");
 
     yield setState(tree, {
       expanded: new Set("ABCDEFGHIJKLMNO".split(""))
     });
 
     isRenderedTree(document.body.textContent, [
       "A:false",
--- a/devtools/client/memory/components/test/mochitest/test_tree_02.html
+++ b/devtools/client/memory/components/test/mochitest/test_tree_02.html
@@ -10,20 +10,21 @@ Test that collapsed subtrees aren't rend
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <pre id="test">
 <script src="head.js" type="application/javascript;version=1.8"></script>
 <script type="application/javascript;version=1.8">
 window.onload = Task.async(function* () {
   try {
+    let ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
     let React = bRequire("devtools/client/shared/vendor/react");
     let Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
 
-    const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
+    const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
 
     yield setState(tree, {
       expanded: new Set("MNO".split(""))
     });
 
     isRenderedTree(document.body.textContent, [
       "A:false",
       "M:false",
--- a/devtools/client/memory/components/test/mochitest/test_tree_03.html
+++ b/devtools/client/memory/components/test/mochitest/test_tree_03.html
@@ -10,20 +10,21 @@ Test Tree's autoExpandDepth.
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <pre id="test">
 <script src="head.js" type="application/javascript;version=1.8"></script>
 <script type="application/javascript;version=1.8">
 window.onload = Task.async(function* () {
   try {
+    let ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
     let React = bRequire("devtools/client/shared/vendor/react");
     let Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
 
-    const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
+    const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
 
     yield setProps(tree, {
       autoExpandDepth: 1
     });
 
     isRenderedTree(document.body.textContent, [
       "A:false",
       "-B:false",
--- a/devtools/client/memory/components/test/mochitest/test_tree_04.html
+++ b/devtools/client/memory/components/test/mochitest/test_tree_04.html
@@ -10,19 +10,20 @@ Test that we only render visible tree it
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <pre id="test">
 <script src="head.js" type="application/javascript;version=1.8"></script>
 <script type="application/javascript;version=1.8">
 window.onload = Task.async(function* () {
   try {
+    const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
     const React = bRequire("devtools/client/shared/vendor/react");
     const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
-    const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
+    const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
 
     yield setState(tree, {
       expanded: new Set("ABCDEFGHIJKLMNO".split("")),
       height: 3,
       scroll: 1
     });
 
     isRenderedTree(document.body.textContent, [
--- a/devtools/client/memory/components/test/mochitest/test_tree_05.html
+++ b/devtools/client/memory/components/test/mochitest/test_tree_05.html
@@ -11,20 +11,21 @@ Test focusing with the Tree component.
 </head>
 <body>
 <pre id="test">
 <script src="head.js" type="application/javascript;version=1.8"></script>
 <script type="application/javascript;version=1.8">
 
 window.onload = Task.async(function* () {
   try {
+    const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
     const React = bRequire("devtools/client/shared/vendor/react");
     const { Simulate } = React.addons.TestUtils;
     const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
-    const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
+    const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
 
     yield setState(tree, {
       focused: "G",
       expanded: new Set("ABCDEFGHIJKLMNO".split(""))
     });
 
     isRenderedTree(document.body.textContent, [
       "A:false",
--- a/devtools/client/memory/components/test/mochitest/test_tree_06.html
+++ b/devtools/client/memory/components/test/mochitest/test_tree_06.html
@@ -10,20 +10,21 @@ Test keyboard navigation with the Tree c
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <pre id="test">
 <script src="head.js" type="application/javascript;version=1.8"></script>
 <script type="application/javascript;version=1.8">
 window.onload = Task.async(function* () {
   try {
+    const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
     const React = bRequire("devtools/client/shared/vendor/react");
     const { Simulate } = React.addons.TestUtils;
     const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
-    const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
+    const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
 
     yield setState(tree, {
       expanded: new Set("ABCDEFGHIJKLMNO".split(""))
     });
 
     // UP ----------------------------------------------------------------------
 
     info("Up to the previous sibling.");
--- a/devtools/client/memory/components/test/mochitest/test_tree_07.html
+++ b/devtools/client/memory/components/test/mochitest/test_tree_07.html
@@ -11,19 +11,20 @@ Test that arrows get the open attribute 
   <link rel="stylesheet" href="chrome://browser/skin/devtools/light-theme.css" type="text/css">
 </head>
 <body>
 <pre id="test">
 <script src="head.js" type="application/javascript;version=1.8"></script>
 <script type="application/javascript;version=1.8">
 window.onload = Task.async(function* () {
   try {
+    const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
     const React = bRequire("devtools/client/shared/vendor/react");
     const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
-    const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
+    const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
 
     yield setProps(tree, {
       renderItem: (item, depth, focused, arrow) => {
         return React.DOM.div(
           {
             id: item,
             style: { marginLeft: depth * 16 + "px" }
           },
--- a/devtools/client/memory/components/test/mochitest/test_tree_08.html
+++ b/devtools/client/memory/components/test/mochitest/test_tree_08.html
@@ -12,20 +12,21 @@ other inputs.
   <link rel="stylesheet" href="chrome://browser/skin/devtools/light-theme.css" type="text/css">
 </head>
 <body>
 <pre id="test">
 <script src="head.js" type="application/javascript;version=1.8"></script>
 <script type="application/javascript;version=1.8">
 window.onload = Task.async(function* () {
   try {
+    const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
     const React = bRequire("devtools/client/shared/vendor/react");
     const { Simulate } = React.addons.TestUtils;
     const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
-    const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
+    const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
 
     const input = document.createElement("input");
     document.body.appendChild(input);
 
     input.focus();
     is(document.activeElement, input, "The text input should be focused.");
 
     Simulate.click(document.querySelector(".tree-node"));
--- a/devtools/client/memory/initializer.js
+++ b/devtools/client/memory/initializer.js
@@ -4,17 +4,18 @@
 
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 const BrowserLoaderModule = {};
 Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
 const { require } = BrowserLoaderModule.BrowserLoader("resource://devtools/client/memory/", this);
 const { Task } = require("resource://gre/modules/Task.jsm");
-const { createFactory, createElement, render, unmountComponentAtNode } = require("devtools/client/shared/vendor/react");
+const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
+const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 const App = createFactory(require("devtools/client/memory/app"));
 const Store = require("devtools/client/memory/store");
 const { assert } = require("devtools/shared/DevToolsUtils");
 
 /**
  * The current target, toolbox, MemoryFront, and HeapAnalysesClient, set by this tool's host.
  */
@@ -25,22 +26,22 @@ var gToolbox, gTarget, gFront, gHeapAnal
  */
 var gStore, gRoot, gApp, gProvider, unsubscribe, isHighlighted;
 
 var initialize = Task.async(function*() {
   gRoot = document.querySelector("#app");
   gStore = Store();
   gApp = createElement(App, { toolbox: gToolbox, front: gFront, heapWorker: gHeapAnalysesClient });
   gProvider = createElement(Provider, { store: gStore }, gApp);
-  render(gProvider, gRoot);
+  ReactDOM.render(gProvider, gRoot);
   unsubscribe = gStore.subscribe(onStateChange);
 });
 
 var destroy = Task.async(function*() {
-  const ok = unmountComponentAtNode(gRoot);
+  const ok = ReactDOM.unmountComponentAtNode(gRoot);
   assert(ok, "Should successfully unmount the memory tool's top level React component");
 
   unsubscribe();
 
   gStore, gRoot, gApp, gProvider, unsubscribe, isHighlighted = null;
 });
 
 /**
--- a/devtools/client/shared/vendor/REACT_UPGRADING
+++ b/devtools/client/shared/vendor/REACT_UPGRADING
@@ -13,8 +13,15 @@ the `react.js` here is the dev environme
 * cp build/react-with-addons.js <gecko-dev>/devtools/client/shared/vendor/react.js
 
 For production, which we do not currently have:
 * NODE_ENV=production grunt build
 * cp build/react-with-addons.js <gecko-dev>/devtools/client/shared/vendor/react.js
 
 The second build produces a non-minified React file but with all the
 sanity checks that incur a perf hit removed.
+
+You also need to copy the ReactDOM package. It requires React, so
+right now we are just manually changing the path from `react` to
+`devtools/client/shared/vendor/react`.
+
+* cp build/react-dom.js <gecko-dev>/devtools/client/shared/vendor/react-dom.js
+* (change `require('react')` at the top of the file to the right path)
--- a/devtools/client/shared/vendor/moz.build
+++ b/devtools/client/shared/vendor/moz.build
@@ -1,11 +1,12 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'react-dom.js',
     'react-redux.js',
     'react.js',
     'redux.js',
 )
new file mode 100644
--- /dev/null
+++ b/devtools/client/shared/vendor/react-dom.js
@@ -0,0 +1,31 @@
+// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js
+;(function(f) {
+  // CommonJS
+  if (typeof exports === "object" && typeof module !== "undefined") {
+    module.exports = f(require('devtools/client/shared/vendor/react'));
+
+  // RequireJS
+  } else if (typeof define === "function" && define.amd) {
+    define(['react'], f);
+
+  // <script>
+  } else {
+    var g
+    if (typeof window !== "undefined") {
+      g = window;
+    } else if (typeof global !== "undefined") {
+      g = global;
+    } else if (typeof self !== "undefined") {
+      g = self;
+    } else {
+      // works providing we're not in "use strict";
+      // needed for Java 8 Nashorn
+      // see https://github.com/facebook/react/issues/3037
+      g = this;
+    }
+    g.ReactDOM = f(g.React);
+  }
+
+})(function(React) {
+  return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+});