From 04d7a1bbd1663ed77c7e5ed05a45e038bb7ed43e Mon Sep 17 00:00:00 2001 From: Brian Ford Date: Tue, 9 Jul 2013 19:11:22 -0700 Subject: [PATCH] message passing nonsense --- js/background.js | 9 +++- js/controllers/ModelCtrl.js | 37 +------------ js/directives/jsonTree.js | 60 +++------------------ js/inject/debug.js | 103 ++++++++++++++++++++++++++++++++++++ js/services/appContext.js | 15 ++++-- js/services/appModel.js | 28 ++++++---- 6 files changed, 151 insertions(+), 101 deletions(-) diff --git a/js/background.js b/js/background.js index ea05be3..d0a2e94 100644 --- a/js/background.js +++ b/js/background.js @@ -1,6 +1,6 @@ // notify of page refreshes -chrome.extension.onConnect.addListener(function(port) { +chrome.extension.onConnect.addListener(function (port) { port.onMessage.addListener(function (msg) { if (msg.action === 'register') { var respond = function (tabId, changeInfo, tab) { @@ -16,4 +16,11 @@ chrome.extension.onConnect.addListener(function(port) { }); } }); + + chrome.extension.onMessage.addListener(function (msg) { + if (msg.action === 'modelChange') { + port.postMessage(msg); + } + }); }); + diff --git a/js/controllers/ModelCtrl.js b/js/controllers/ModelCtrl.js index 6dc7c5d..43c3f21 100644 --- a/js/controllers/ModelCtrl.js +++ b/js/controllers/ModelCtrl.js @@ -27,41 +27,8 @@ angular.module('panelApp').controller('ModelCtrl', function ModelCtrl($scope, ap $scope.enableInspector = appModel.enableInspector; - - $scope.$on('poll', function () { - - // get the list of root scopes - appModel.getRootScopes(function (rootScopes) { - $scope.$apply(function () { - $scope.roots = rootScopes; - if ($scope.roots.length === 0) { - $scope.selectedRoot = null; - } else if (!$scope.selectedRoot) { - $scope.selectedRoot = $scope.roots[0]; - } - if ($scope.selectedRoot && !$scope.selectedScope) { - $scope.selectedScope = $scope.selectedRoot; - } - }); - }); - - // get scope tree - if ($scope.selectedRoot) { - appModel.getScopeTree($scope.selectedRoot, function (tree) { - $scope.$apply(function () { - $scope.tree = tree; - }); - }); - } - - // get models on the selected scope - if ($scope.selectedScope) { - appModel.getModel($scope.selectedScope, function (model) { - $scope.$apply(function () { - $scope.model = model; - }); - }); - } + appContext.watchModelChange(function (msg) { + console.log(msg); }); diff --git a/js/directives/jsonTree.js b/js/directives/jsonTree.js index d660222..6fd5ceb 100644 --- a/js/directives/jsonTree.js +++ b/js/directives/jsonTree.js @@ -1,64 +1,20 @@ -angular.module('panelApp').directive('batJsonTree', function($compile) { +angular.module('panelApp').directive('batJsonTree', function($compile, appModel) { return { restrict: 'E', terminal: true, scope: { - val: '=' - //edit: '=', + scopeId: '=' }, link: function (scope, element, attrs) { - // this is more complicated then it should be - // see: https://github.com/angular/angular.js/issues/898 - var buildDom = function (object) { - var html = ''; - var prop; - if (object === undefined) { - html += 'undefined'; - } else if (object === null) { - html += 'null'; - } else if (object instanceof Array) { - var i; - html += '
[ '; - if (object.length > 0) { - html += buildDom(object[0]); - for (i = 1; i < object.length; i++) { - html += ', ' + buildDom(object[i]); - } - } - html += ' ]
'; - } else if (object instanceof Object) { - html += ' { '; - for (prop in object) { - if (object.hasOwnProperty(prop)) { - html += '
' + prop + ': ' + buildDom(object[prop]) + '
'; - } - } - html += ' } '; - } else { - html += '' + object.toString() + ''; - } - return html; - }; + var watching = []; - var isEmpty = function (object) { - var prop; - for (prop in object) { - if (object.hasOwnProperty(prop)) { - return false; - } - } - return true; - }; + console.log(element); - scope.$watch('val', function (newVal, oldVal) { - if (newVal === null) { - element.html('
Select a scope to view its models.
'); - } else if (isEmpty(newVal)) { - element.html('
{ This scope has no models }
'); - } else { - element.html('
' + buildDom(newVal) + '
'); - } + var scopeId = '003'; + + appModel.getModel(scopeId, [], function (obj) { + console.log(obj); }); } }; diff --git a/js/inject/debug.js b/js/inject/debug.js index 5b55ece..0fce385 100644 --- a/js/inject/debug.js +++ b/js/inject/debug.js @@ -57,6 +57,24 @@ var inject = function () { performance.now = performance.webkitNow; } + // Send notifications from app context to devtools context + // ======================================================= + + var eventProxyElement = document.createElement('div'); + eventProxyElement.id = '__ngDebugElement'; + eventProxyElement.style.display = 'none'; + document.body.appendChild(eventProxyElement); + + var customEvent = document.createEvent('Event'); + customEvent.initEvent('myCustomEvent', true, true); + + function fireCustomEvent (data) { + eventProxyElement.innerText = data; + eventProxyElement.dispatchEvent(customEvent); + } + + + // Based on cycle.js // https://github.com/douglascrockford/JSON-js/blob/master/cycle.js @@ -269,6 +287,8 @@ var inject = function () { return ids; }, + fireCustomEvent: fireCustomEvent, + // returns null or cached scope getModel: function (id) { if (debug.scopeDirty[id]) { @@ -277,6 +297,75 @@ var inject = function () { } }, + getSomeModel: function (id, path) { + path = path || []; + + var dest = debug.scopes[id], + segment; + + if (!dest) { + console.log('no scope'); + return; + } + + while (path.length > 0) { + segment = path.shift(); + dest = dest[segment]; + if (!dest) { + console.log('no dest'); + return; + } + } + + if (dest instanceof Array) { + return { + '~array-length': dest.length + }; + } else if (typeof dest === 'object') { + return Object. + keys(dest). + filter(function (key) { + return key[0] !== '$' || key[1] !== '$'; + }). + reduce(function (obj, prop) { + obj[prop] = dest[prop] instanceof Array ? + { '~array-length': dest[prop].length } : + typeof dest[prop] === 'object' ? + { '~object': true } : + dest[prop]; + + return obj; + }, {}); + } else { + return dest; + } + }, + + setSomeModel: function (id, path, value) { + path = path || []; + + var dest = debug.scopes[id], + segment; + + if (!dest) { + return; + } + + while (path.length > 1) { + segment = path.shift(); + dest = dest[segment]; + if (!dest) { + return; + } + } + + if (dest[path[0]]) { + debug.scopes[id].$apply(function batarangEditModel () { + dest[path[0]] = value; + }); + } + }, + getScopeTree: function (id) { if (debug.scopeTreeDirty[id] === false) { return; @@ -889,6 +978,20 @@ var inject = function () { return script; }())); + + var eventProxyElement = document.getElementById('__ngDebugElement'); + + if (eventProxyElement) { + eventProxyElement.addEventListener('myCustomEvent', function() { + var eventData = eventProxyElement.innerText; + chrome.extension.sendMessage({ + action: 'modelChange', + value: eventData + }); + }); + document.removeEventListener('DOMContentLoaded', inject); + } + }; // only inject if cookie is set diff --git a/js/services/appContext.js b/js/services/appContext.js index 05e9275..a0eed85 100644 --- a/js/services/appContext.js +++ b/js/services/appContext.js @@ -1,6 +1,8 @@ // Service for running code in the context of the application being debugged angular.module('panelApp').factory('appContext', function (chromeExtension) { + var port = chrome.extension.connect(); + // Public API // ========== return { @@ -82,18 +84,23 @@ angular.module('panelApp').factory('appContext', function (chromeExtension) { // TODO: move to chromeExtension? watchRefresh: function (cb) { - var port = chrome.extension.connect(); port.postMessage({ action: 'register', inspectedTabId: chrome.devtools.inspectedWindow.tabId }); - port.onMessage.addListener(function(msg) { + port.onMessage.addListener(function (msg) { if (msg === 'refresh') { cb(); } }); - port.onDisconnect.addListener(function (a) { - console.log(a); + }, + + // TODO: move to chromeExtension? + watchModelChange: function (cb) { + port.onMessage.addListener(function (msg) { + if (msg.action === 'modelChange') { + cb(msg); + } }); } diff --git a/js/services/appModel.js b/js/services/appModel.js index be99b36..6304a4a 100644 --- a/js/services/appModel.js +++ b/js/services/appModel.js @@ -28,19 +28,29 @@ angular.module('panelApp').factory('appModel', function (chromeExtension, appCon }); }, - // only runs callback if model has changed since last call - getModel: function (id, callback) { + getModel: function (id, path, callback) { if (!id) { return; } chromeExtension.eval(function (window, args) { - return window.__ngDebug.getModel(args.id); - }, {id: id}, function (tree) { - if (tree) { - _scopeCache[id] = tree; - } - callback(_scopeCache[id]); - }); + return window.__ngDebug.getSomeModel(args.id, args.path); + }, { + id: id, + path: path + }, callback); + }, + + setModel: function (id, path, value, callback) { + if (!id) { + return; + } + chromeExtension.eval(function (window, args) { + return window.__ngDebug.setSomeModel(args.id, args.path, args.value); + }, { + id: id, + path: path, + value: value + }, callback); }, getScopeTree: function (id, callback) {