Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of git://github.com/ajaxorg/cloud9 into sync-fixes

Conflicts:
	configs/default.js
  • Loading branch information...
commit 5e292c071f38c08b8203d577edf818ba8ccc6bfc 2 parents 33b8862 + 01bd3c7
@cadorn cadorn authored
Showing with 573 additions and 284 deletions.
  1. +1 −1  Makefile
  2. +12 −0 Makefile.dryice.js
  3. +1 −1  README.md
  4. +2 −2 configs/default.js
  5. +17 −17 package.json
  6. +1 −0  plugins-client/cloud9.core/www/core/ide.js
  7. +8 −2 plugins-client/ext.code/code.js
  8. +0 −1  plugins-client/ext.codecomplete/complete_util.js
  9. +6 −1 plugins-client/ext.console/console.js
  10. +10 −0 plugins-client/ext.editors/editors.js
  11. +13 −2 plugins-client/ext.gotofile/gotofile.js
  12. +1 −1  plugins-client/ext.help/help.js
  13. +2 −1  plugins-client/ext.jslanguage/narcissus_jshint.js
  14. +13 −0 plugins-client/ext.jslanguage/narcissus_jshint_test.js
  15. +28 −11 plugins-client/ext.language/complete.js
  16. +10 −5 plugins-client/ext.language/keyhandler.js
  17. +4 −4 plugins-client/ext.language/language.js
  18. +8 −3 plugins-client/ext.language/outline.js
  19. +1 −1  plugins-client/ext.language/settings.xml
  20. +12 −5 plugins-client/ext.language/worker.js
  21. BIN  plugins-client/ext.main/style/icons/file-tree-load-spinner-selected.gif
  22. BIN  plugins-client/ext.main/style/icons/file-tree-load-spinner.gif
  23. +12 −4 plugins-client/ext.main/style/skins.xml
  24. +2 −2 plugins-client/ext.noderunner/noderunner.js
  25. +6 −2 plugins-client/ext.revisions/revisions.js
  26. +1 −1  plugins-client/ext.sync/sync.js
  27. +1 −1  plugins-client/ext.uploadfiles/uploadfiles.js
  28. +1 −1  plugins-client/lib.ace/www/theme/theme-clouds_midnight.js
  29. +1 −1  plugins-client/lib.ace/www/theme/theme-cobalt.js
  30. +1 −1  plugins-client/lib.ace/www/theme/theme-idle_fingers.js
  31. +1 −1  plugins-client/lib.ace/www/theme/theme-kr_theme.js
  32. +2 −2 plugins-client/lib.ace/www/theme/theme-merbivore.js
  33. +1 −1  plugins-client/lib.ace/www/theme/theme-merbivore_soft.js
  34. +1 −1  plugins-client/lib.ace/www/theme/theme-mono_industrial.js
  35. +1 −1  plugins-client/lib.ace/www/theme/theme-pastel_on_dark.js
  36. +1 −1  plugins-client/lib.ace/www/theme/theme-tomorrow.js
  37. +1 −1  plugins-client/lib.ace/www/theme/theme-tomorrow_night.js
  38. +1 −1  plugins-client/lib.ace/www/theme/theme-tomorrow_night_bright.js
  39. +1 −1  plugins-client/lib.ace/www/theme/theme-tomorrow_night_eighties.js
  40. +1 −1  plugins-client/lib.ace/www/theme/theme-twilight.js
  41. +1 −1  plugins-client/lib.ace/www/theme/theme-vibrant_ink.js
  42. +12 −8 plugins-client/lib.apf/www/apf-packaged/apf_release.js
  43. +28 −30 plugins-client/lib.apf/www/apf/elements/codeeditor.js
  44. +21 −6 plugins-client/lib.apf/www/apf/elements/dbg/v8debugger.js
  45. +131 −64 plugins-client/lib.apf/www/apf/elements/debugger.js
  46. +38 −21 plugins-server/cloud9.core/ide-plugin.js
  47. +11 −16 plugins-server/cloud9.core/ide.js
  48. +4 −2 plugins-server/cloud9.core/user.js
  49. +6 −7 plugins-server/cloud9.fs/dav/permission.js
  50. +33 −16 plugins-server/cloud9.ide.revisions/revisions.js
  51. +39 −10 plugins-server/cloud9.ide.run-node/run-node.js
  52. +18 −14 plugins-server/cloud9.ide.run-npm-module/run-npm-module.js
  53. +5 −6 plugins-server/cloud9.ide.shell/shell.js
  54. +0 −1  plugins-server/cloud9.ide.watcher/watcher.js
  55. +16 −0 plugins-server/cloud9.routes/package.json
  56. +24 −0 plugins-server/cloud9.routes/routes-plugin.js
View
2  Makefile
@@ -66,7 +66,7 @@ plugins-client/lib.ace/www/worker/worker.js : $(wildcard plugins-client/ext.lang
ln -s `pwd`/plugins-client/ext.language /tmp/c9_worker_build/ext/language
ln -s `pwd`/plugins-client/ext.codecomplete /tmp/c9_worker_build/ext/codecomplete
ln -s `pwd`/plugins-client/ext.jslanguage /tmp/c9_worker_build/ext/jslanguage
- ./Makefile.dryice.js worker
+ node Makefile.dryice.js worker
cp node_modules/ace/build/src/worker* plugins-client/lib.ace/www/worker
# copies built ace modes
View
12 Makefile.dryice.js 100755 → 100644
@@ -41,6 +41,16 @@ function worker(project) {
var worker = copy.createDataObject();
var workerProject = copy.createCommonJsProject(project);
+
+ // We don't get a return value from dryice, so we monkey patch error handling
+ var yeOldeError = console.error;
+ console.error = function() {
+ yeOldeError();
+ yeOldeError("@@@@ FATAL ERROR: DRYICE FAILED", arguments);
+ yeOldeError();
+ process.exit(1);
+ };
+
copy({
source: [
copy.source.commonjs({
@@ -73,6 +83,8 @@ function worker(project) {
filter: [ /* copy.filter.uglifyjs */],
dest: __dirname + "/plugins-client/lib.ace/www/worker/worker.js"
});
+
+ console.error = yeOldeError;
}
function filterTextPlugin(text) {
View
2  README.md
@@ -36,7 +36,7 @@ We support the newer versions of Chrome, Firefox and Safari.
Requirements:
- * NodeJS `>= 0.6.15`
+ * NodeJS `>= 0.6.15` (node 0.8.x will *not work* at the moment!)
* NPM `>= 1.1.16`
Install:
View
4 configs/default.js
@@ -20,7 +20,7 @@ var fsUrl = "/workspace";
var vfsUrl = "/vfs";
var port = argv.p || process.env.PORT || 3131;
-var host = argv.l || "localhost";
+var host = argv.l || process.env.IP || "localhost";
var config = [
{
@@ -58,7 +58,7 @@ var config = [
debug: false,
fsUrl: fsUrl,
hosted: false,
- socketIoTransports: [/*"websocket", */"htmlfile", "xhr-multipart", "xhr-polling"],
+ socketIoTransports: ["websocket", "htmlfile", "xhr-multipart", "xhr-polling"],
sidkey: "cloud9.sid." + port,
bundledPlugins: [
"helloworld"
View
34 package.json
@@ -12,44 +12,44 @@
"pm": "sm",
"dependencies": {
- "socket.io": "0.9.x",
"connect": "1.8.x",
"sourcemint-loader-js": "0.x",
"sourcemint-platform-nodejs": "0.x",
- "http-error": "~0.0.1",
- "simple-template": "~0.0.1",
+ "http-error": "0.0.1",
+ "simple-template": "0.0.1",
- "optimist": "~0.3.1",
+ "optimist": "0.3.4",
"dryice": "0.4.2",
"mappings": "0.1.x",
- "amd-loader": "~0.0.4",
+ "amd-loader": "0.0.4",
"async": "0.1.21",
- "netutil": "~0.0.1",
- "architect": ">=0.1.4",
- "connect-architect": "~0.0.1"
+ "netutil": "0.0.1",
+ "architect": "0.1.4",
+ "connect-architect": "0.0.3"
},
"devDependencies": {
- "nodeunit": "~0.7.4",
- "sinon": "~1.3.4",
- "rimraf": "~2.0.1",
- "vfs-local": "~0.0.0",
- "vfs-nodefs-adapter": "~0.0.1"
+ "nodeunit": "0.7.4",
+ "sinon": "1.3.4",
+ "rimraf": "2.0.1",
+ "vfs-local": "0.1.4",
+ "vfs-nodefs-adapter": "0.0.4"
},
"mappings": {
"ace": ["npm", "https://github.com/ajaxorg/ace/tarball/78975a0fc26eda9137b9caf11b63fe6f1ea7283f"],
- "apf": ["npm", "https://github.com/ajaxorg/apf/tarball/0f03564345da764409b00e551a681337c7e1df96"],
+ "apf": ["npm", "https://github.com/ajaxorg/apf/tarball/855302855ba9e2953f74f93cd5ea56af2b6bf543"],
"asyncjs": ["npm", "https://github.com/ajaxorg/async.js/tarball/0b4ed5608a32c280a7690b5f52883d8d1fc0de08"],
- "jsDAV": ["npm", "https://github.com/ajaxorg/jsDAV/tarball/7fc5b36a5074668f40aad8b45f82a6fbbec04c88"],
+ "jsDAV": ["npm", "https://github.com/ajaxorg/jsDAV/tarball/aae84622919668b254733238a07d4673cbb863db"],
"v8debug": ["npm", "https://github.com/ajaxorg/lib-v8debug/tarball/d2fac9b09724cb2e75e2807191eace9bc27d3b52"],
"packager": ["npm", "https://github.com/ajaxorg/packager/tarball/ae07ff93310d1625c48119e98141bbe5b2c26200"],
"vfs": ["npm", "https://github.com/c9/vfs/tarball/be43f8b32f9b1c69923dd85ec9be7eb6836bbb29"],
"vfs-architect":["npm", "https://github.com/c9/vfs-architect/tarball/43bd19b9e7b2ddb95bdc1116143ce7fb22c6a5d3"],
- "treehugger": ["npm", "https://github.com/ajaxorg/treehugger/tarball/cb8fd0483417ac6ffb8532b994d23dbf13ad9022"],
- "socket.io-client": ["npm", "https://github.com/ajaxorg/socket.io-client/tarball/9d0c0631f390538134a7d1f841db2c72d79f8cb4"]
+ "treehugger": ["npm", "https://github.com/ajaxorg/treehugger/tarball/46f9d8ffdb159a2c206d41ed6ad877f471bb1e2f"],
+ "socket.io": ["npm", "https://github.com/ajaxorg/socket.io/tarball/7aa252bab49e6bbc314dc2678b108b6e0876007a"],
+ "socket.io-client": ["npm", "https://github.com/ajaxorg/socket.io-client/tarball/35f0763ffcaa7ccc3c664460667577e77da82b10"]
},
"repository" : {
View
1  plugins-client/cloud9.core/www/core/ide.js
@@ -126,6 +126,7 @@ define(function(require, exports, module) {
retries++;
if (retries < 10 || retries < 60 && retries % 10 == 0 || retries % 50 == 0) {
sock.disconnect();
+ sock.remainingTransports = null;
sock.connect();
if (retries == 5) {
View
10 plugins-client/ext.code/code.js
@@ -456,8 +456,14 @@ module.exports = ext.register("ext/code/code", {
ide.addEventListener("tab.afterswitch", function(e) {
var editor = _self.amlEditor;
- if (typeof editor != "undefined")
- editor.afterOpenFile(editor.getSession());
+ if (typeof editor !== "undefined") {
+ // path without dav prefix and without trailing slashes
+ var path = (e.nextPage.name.indexOf(e.currentTarget.davPrefix) === 0 ?
+ e.nextPage.name.substr(e.currentTarget.davPrefix.length) :
+ e.nextPage.name).replace(/^\/+/, "")
+
+ editor.afterOpenFile(editor.getSession(), path);
+ }
});
// Override ACE key bindings (conflict with goto definition)
View
1  plugins-client/ext.codecomplete/complete_util.js
@@ -43,7 +43,6 @@ function findCompletions(prefix, allIdentifiers) {
return matches;
}
-
exports.retrievePreceedingIdentifier = retrievePreceedingIdentifier;
exports.findCompletions = findCompletions;
View
7 plugins-client/ext.console/console.js
@@ -99,6 +99,11 @@ module.exports = ext.register("ext/console/console", {
if (proc.extra) {
command_id = proc.extra.command_id;
original_line = proc.extra.original_line;
+
+ if (!original_line) {
+ continue;
+ }
+
this.createOutputBlock(this.getPrompt(original_line), false, command_id);
if (proc.type === "run-npm") {
@@ -114,7 +119,7 @@ module.exports = ext.register("ext/console/console", {
this.pidToTracerMap[spi] = command_id;
var containerEl = document.getElementById("console_section" + command_id);
- if (!containerEl) {
+ if (containerEl) {
containerEl.setAttribute("rel", command_id);
apf.setStyleClass(containerEl, "has_pid");
}
View
10 plugins-client/ext.editors/editors.js
@@ -746,6 +746,16 @@ module.exports = ext.register("ext/editors/editors", {
settings.model.setQueryValue("editors/code/@fontsize", --currSize < 1 ? 1 : currSize);
}
});
+
+ menus.addItemByPath("View/Font Size/", null, 199),
+
+ menus.addItemByPath("View/Font Size/Increase Font Size", new apf.item({
+ command : "largerfont"
+ }), 1);
+
+ menus.addItemByPath("View/Font Size/Decrease Font Size", new apf.item({
+ command : "smallerfont"
+ }), 2);
menus.addItemByPath("View/Tab Buttons", new apf.item({
type: "check",
View
15 plugins-client/ext.gotofile/gotofile.js
@@ -407,8 +407,19 @@ module.exports = ext.register("ext/gotofile/gotofile", {
apf.setOpacity(winGoToFile.$ext, 1);
}
- txtGoToFile.select();
- txtGoToFile.focus();
+ if (!txtGoToFile.inited) {
+ setTimeout(function(){
+ afterTbRendered();
+ });
+ }
+ else {
+ afterTbRendered();
+ }
+
+ function afterTbRendered(){
+ txtGoToFile.focus();
+ txtGoToFile.inited = true;
+ }
// If we had a filter and new content, lets refilter
if (this.lastSearch) {
View
2  plugins-client/ext.help/help.js
@@ -77,7 +77,7 @@ define(function(require, exports, module) {
menus.addItemByPath("Help/Get in Touch/Twitter (for general Cloud9 tweets)", new apf.item({ onclick : function(){ window.open('https://twitter.com/#!/cloud9ide'); }}), c += 100);
menus.addItemByPath("Help/Get in Touch/Facebook for Cloud9", new apf.item({ onclick : function(){ window.open('https://www.facebook.com/Cloud9IDE'); }}), c += 100);
- if (window.cloud9config.hosted) {
+ if (window.cloud9config.hosted || (ide.local && ide.onLine)) {
mnuHelp.addEventListener("prop.visible", function(e) {
if (e.value) {
var blogURL = window.location.protocol + "//" + window.location.host + "/site/?json=get_tag_posts&tag_slug=changelog";
View
3  plugins-client/ext.jslanguage/narcissus_jshint.js
@@ -32,7 +32,8 @@ handler.analyze = function(doc, ast, callback) {
passfail: false,
devel: true,
browser: true,
- node: true
+ node: true,
+ esnext: true
});
lint.errors.forEach(function(warning) {
View
13 plugins-client/ext.jslanguage/narcissus_jshint_test.js
@@ -50,6 +50,19 @@ module.exports = {
var worker = new LanguageWorker(emitter);
worker.register("ext/jslanguage/narcissus_jshint");
worker.switchFile("no-errors.js", "javascript", "var foo = function() {};\nfoo && foo();");
+ },
+
+ "test JSHint const support" : function(next) {
+ var emitter = Object.create(EventEmitter);
+ emitter.emit = emitter._dispatchEvent;
+ emitter.on("markers", function(markers) {
+ console.log(markers);
+ assert.equal(markers.length, 0);
+ next();
+ });
+ var worker = new LanguageWorker(emitter);
+ worker.register("ext/jslanguage/narcissus_jshint");
+ worker.switchFile("no-errors.js", "javascript", "const foo = 1;");
}
};
View
39 plugins-client/ext.language/complete.js
@@ -10,7 +10,7 @@ var ide = require("core/ide");
var editors = require("ext/editors/editors");
var dom = require("ace/lib/dom");
var keyhandler = require("ext/language/keyhandler");
-var completionUtil = require("ext/codecomplete/complete_util");
+var editors = require("ext/editors/editors");
var lang = require("ace/lib/lang");
var language;
@@ -34,8 +34,8 @@ var deferredInvoke = lang.deferredCall(function() {
var editor = editors.currentEditor.ceEditor.$editor;
var pos = editor.getCursorPosition();
var line = editor.getSession().getDocument().getLine(pos.row);
- if(keyhandler.preceededByIdentifier(line, pos.column) ||
- line[pos.column - 1] === '.' ||
+ if (keyhandler.preceededByIdentifier(line, pos.column) ||
+ (line[pos.column - 1] === '.' && (!line[pos.column] || !line[pos.column].match(ID_REGEX))) ||
keyhandler.isRequireJSCall(line, pos.column)) {
module.exports.invoke(true);
}
@@ -45,9 +45,10 @@ var deferredInvoke = lang.deferredCall(function() {
isInvokeScheduled = false;
});
var isInvokeScheduled = false;
+var ignoreMouseOnce = false;
var drawDocInvoke = lang.deferredCall(function() {
- if (isPopupVisible()) {
+ if (isPopupVisible() && complete.matches[complete.selectedIdx].doc) {
isDocShown = true;
txtCompleterDoc.parentNode.show();
}
@@ -92,6 +93,10 @@ function retrieveFollowingIdentifier(text, pos) {
return buf;
}
+function isJavaScript() {
+ return editors.currentEditor.amlEditor.syntax === "javascript";
+}
+
/**
* Replaces the preceeding identifier (`prefix`) with `newText`, where ^^
* indicates the cursor position after the replacement.
@@ -104,7 +109,7 @@ function replaceText(editor, prefix, match) {
var line = editor.getSession().getLine(pos.row);
var doc = editor.getSession().getDocument();
- if (match.replaceText === "require(^^)") {
+ if (match.replaceText === "require(^^)" && isJavaScript()) {
newText = "require(\"^^\")";
if (!isInvokeScheduled)
setTimeout(deferredInvoke, AUTO_OPEN_DELAY);
@@ -137,8 +142,18 @@ function replaceText(editor, prefix, match) {
doc.removeInLine(pos.row, pos.column - prefix.length, pos.column + postfix.length);
doc.insert({row: pos.row, column: pos.column - prefix.length}, paddedLines);
+
+ var cursorCol = pos.column + colOffset - prefix.length;
+
+ if (line.substring(0, pos.column).match(/require\("[^\"]+$/) && isJavaScript()) {
+ if (line.substr(pos.column + postfix.length, 1).match(/['"]/) || paddedLines.substr(0, 1) === '"')
+ cursorCol++;
+ if (line.substr(pos.column + postfix.length + 1, 1) === ')')
+ cursorCol++;
+ }
setTimeout(function() {
- editor.moveCursorTo(pos.row + rowOffset, pos.column + colOffset - prefix.length);
+ var cursorPos = { row: pos.row + rowOffset, column: cursorCol };
+ editor.selection.setSelectionRange({ start: cursorPos, end: cursorPos });
}, 50);
}
@@ -217,6 +232,8 @@ module.exports = {
var innerCompletionBoxHeight = Math.min(10 * this.lineHeight, innerBoxLength * (this.lineHeight));
txtCompleterHolder.$ext.style.height = innerCompletionBoxHeight + "px";
+ ignoreMouseOnce = !isPopupVisible();
+
apf.popup.show("completionBox", {
x : (prefix.length * -_self.cursorConfig.characterWidth) - 11,
y : _self.cursorConfig.lineHeight,
@@ -284,6 +301,10 @@ module.exports = {
html += '</span>';
matchEl.innerHTML = html;
matchEl.addEventListener("mouseover", function() {
+ if (ignoreMouseOnce) {
+ ignoreMouseOnce = false;
+ return;
+ }
_self.matchEls[_self.selectedIdx].className = CLASS_UNSELECTED;
_self.selectedIdx = idx;
_self.matchEls[_self.selectedIdx].className = CLASS_SELECTED;
@@ -339,11 +360,6 @@ module.exports = {
onKeyPress : function(e, hashKey, keyCode) {
var _self = this;
- if(keyCode === 9 && !e.shiftKey) // Tab
- keyCode = 40; // Up
- else if(keyCode === 9 && e.shiftKey) // Shift-Tab
- keyCode = 38; // Down
-
if(e.metaKey || e.ctrlKey || e.altKey) {
this.closeCompletionBox();
return;
@@ -372,6 +388,7 @@ module.exports = {
e.preventDefault();
break;
case 13: // Enter
+ case 9: // Tab
var editor = editors.currentEditor.amlEditor.$editor;
replaceText(editor, this.prefix, this.matches[this.selectedIdx]);
this.closeCompletionBox();
View
15 plugins-client/ext.language/keyhandler.js
@@ -8,6 +8,7 @@ define(function(require, exports, module) {
var editors = require("ext/editors/editors");
var completionUtil = require("ext/codecomplete/complete_util");
+var editors = require("ext/editors/editors");
var language;
function hook(ext) {
@@ -43,11 +44,11 @@ function onCommandKey(e) {
}
function typeAlongComplete(e) {
- if(e.metaKey || e.altKey || e.ctrlKey)
+ if (e.metaKey || e.altKey || e.ctrlKey)
return false;
- if(editors.currentEditor.amlEditor.syntax !== "javascript")
+ if (!isJavaScript())
return false;
- if(e.keyCode === 8) { // Backspace
+ if (e.keyCode === 8) { // Backspace
var complete = require("ext/language/complete");
var editor = editors.currentEditor.amlEditor.$editor;
var pos = editor.getCursorPosition();
@@ -59,19 +60,23 @@ function typeAlongComplete(e) {
}
function inputTriggerComplete(text, pasted) {
- if (editors.currentEditor.amlEditor.syntax !== "javascript")
+ if (!isJavaScript())
return false;
if (!pasted && text === "." && language.isInferAvailable())
handleChar(text);
}
function typeAlongCompleteTextInput(text, pasted) {
- if(editors.currentEditor.amlEditor.syntax !== "javascript")
+ if (!isJavaScript())
return false;
if(!pasted)
handleChar(text);
}
+function isJavaScript() {
+ return editors.currentEditor.amlEditor.syntax === "javascript";
+}
+
function handleChar(ch) {
if(ch.match(/[A-Za-z0-9_\$\.]/)) {
var ext = require("ext/language/complete");
View
8 plugins-client/ext.language/language.js
@@ -94,13 +94,13 @@ module.exports = ext.register("ext/language/language", {
});
}, true);
- ide.addEventListener("settings.load", function(){
+ ide.addEventListener("settings.load", function() {
settings.setDefaults("language", [
["jshint", "true"],
["instanceHighlight", "true"],
["undeclaredVars", "true"],
["unusedFunctionArgs", "false"],
- ["continuousComplete", cloud9config.hosted ? "true" : "false"] // always returns false _self.isInferAvailable() ? "true" : "false"]
+ ["continuousCompletion", _self.isInferAvailable() ? "true" : "false"]
]);
});
@@ -108,7 +108,7 @@ module.exports = ext.register("ext/language/language", {
},
isInferAvailable : function() {
- return !!require("core/ext").extLut["ext/jsinfer/jsinfer"];
+ return cloud9config.hosted || !!require("core/ext").extLut["ext/jsinfer/jsinfer"];
},
init : function() {
@@ -202,7 +202,7 @@ module.exports = ext.register("ext/language/language", {
var cursorPos = this.editor.getCursorPosition();
cursorPos.force = true;
this.worker.emit("cursormove", {data: cursorPos});
- isContinuousCompletionEnabled = settings.model.queryValue("language/@continuousComplete") != "false";
+ isContinuousCompletionEnabled = settings.model.queryValue("language/@continuousCompletion") != "false";
this.setPath();
},
View
11 plugins-client/ext.language/outline.js
@@ -158,9 +158,11 @@ module.exports = {
return;
}
- this.fullOutline = event.data.body;
-
var editor = editors.currentEditor;
+ if (!editor || !editor.ceEditor)
+ return;
+
+ this.fullOutline = event.data.body;
var ace = editor.ceEditor.$editor;
var cursor = ace.getCursorPosition();
this.$originalLine = cursor.row + 1;
@@ -219,6 +221,10 @@ module.exports = {
},
renderOutline: function(ignoreFilter) {
+ var editor = editors.currentEditor;
+ if (!editor || !editor.ceEditor)
+ return;
+
ext.initExtension(gotofile);
var filter = ignoreFilter ? "" : txtGoToFile.value.substr(1);
this.isDirty = ignoreFilter;
@@ -233,7 +239,6 @@ module.exports = {
treeOutline.$removeClearMessage();
*/
- var editor = editors.currentEditor;
var ace = editor.ceEditor.$editor;
var selected = this.findCursorInOutline(outline, ace.getCursorPosition());
mdlOutline.load(apf.getXml('<data>' + this.outlineJsonToXml(outline, selected, 'entries') + '</data>'));
View
2  plugins-client/ext.language/settings.xml
@@ -8,7 +8,7 @@
<a:checkbox class="underlined" label="Mark Unused Function Arguments"
value="[language/@unusedFunctionArgs]" skin="checkbox_grey" position="4000"/>
<a:checkbox class="underlined" label="Complete As You Type"
- value="[language/@continuousComplete]" skin="checkbox_grey" position="4000"/>
+ value="[language/@continuousCompletion]" skin="checkbox_grey" position="4000"/>
<a:hbox edge="5 5 2 5" align="center">
<a:label flex="1">Warning Level</a:label>
<a:dropdown default="info" value="[{require('ext/settings/settings').model}::language/@warnLevel]" width="80" height="21">
View
17 plugins-client/ext.language/worker.js
@@ -24,6 +24,7 @@ var WARNING_LEVELS = {
// Leaking into global namespace of worker, to allow handlers to have access
disabledFeatures = {};
+var currentPos;
var LanguageWorker = exports.LanguageWorker = function(sender) {
var _self = this;
@@ -205,7 +206,7 @@ function asyncParForEach(array, fn, callback) {
next();
});
} catch(e) {
- if (e instanceof TypeError)
+ if (e instanceof TypeError || e instanceof ReferenceError)
throw e;
// Ignore parse errors
next();
@@ -287,8 +288,10 @@ function asyncParForEach(array, fn, callback) {
extendedMakers = markers.concat(_self.getLastAggregateActions().markers);
_self.scheduleEmit("markers", _self.filterMarkersBasedOnLevel(extendedMakers));
_self.currentMarkers = markers;
- if (_self.postponedCursorMove)
+ if (_self.postponedCursorMove) {
_self.onCursorMove(_self.postponedCursorMove);
+ _self.postponedCursorMove = null;
+ }
callback();
});
});
@@ -410,6 +413,7 @@ function asyncParForEach(array, fn, callback) {
_self.scheduleEmit("markers", _self.filterMarkersBasedOnLevel(_self.currentMarkers.concat(aggregateActions.markers)));
_self.scheduleEmit("enableRefactorings", aggregateActions.enableRefactorings);
_self.lastCurrentNode = currentNode;
+ _self.lastCurrentPos = currentPos;
_self.setLastAggregateActions(aggregateActions);
_self.scheduleEmit("hint", {
pos: pos,
@@ -422,8 +426,9 @@ function asyncParForEach(array, fn, callback) {
if (this.cachedAst) {
var ast = this.cachedAst;
- var currentNode = ast.findNode({line: pos.row, col: pos.column});
- if (currentNode !== this.lastCurrentNode || pos.force) {
+ var currentPos = {line: pos.row, col: pos.column};
+ var currentNode = ast.findNode(currentPos);
+ if (currentPos != this.lastCurrentPos || currentNode !== this.lastCurrentNode || pos.force) {
cursorMoved();
}
} else {
@@ -490,6 +495,7 @@ function asyncParForEach(array, fn, callback) {
this.$language = language;
this.cachedAst = null;
this.lastCurrentNode = null;
+ this.lastCurrentPos = null;
this.setValue(code);
var doc = this.doc;
asyncForEach(this.handlers, function(handler, next) {
@@ -549,7 +555,8 @@ function asyncParForEach(array, fn, callback) {
_self.parse(function(hAst) {
if(hAst) {
ast = hAst;
- currentNode = ast.findNode({line: pos.row, col: pos.column});
+ currentPos = {line: pos.row, col: pos.column};
+ currentNode = ast.findNode(currentPos);
}
next();
});
View
BIN  plugins-client/ext.main/style/icons/file-tree-load-spinner-selected.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  plugins-client/ext.main/style/icons/file-tree-load-spinner.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
16 plugins-client/ext.main/style/skins.xml
@@ -2843,7 +2843,7 @@
border-radius: 6px 6px 6px 6px;
}
.btn-default-css3.btn-default-css3Focus .border {
-
+ display: block;
}
/*-----------*/
@@ -9454,7 +9454,12 @@
padding : 3px 20px 1px 20px;
}
]]></a:style>
-
+<a:style condition="apf.isGecko"><![CDATA[
+ .tab_console .btncontainer .btntab {
+ float: left;
+ min-width: 70px;
+ }
+]]></a:style>
<a:presentation>
<a:main pages="." buttons="div[1]">
<div class="tab_console">
@@ -12075,7 +12080,6 @@
height:16px;
padding-left:1px;
margin-top:0px;
- margin-left: 21px;
font-family : Tahoma, Arial;
font-size : 11px;
@@ -12102,7 +12106,11 @@
-webkit-box-shadow: 0px 0px 6px #76839A;
box-shadow: 0px 0px 6px #76839A;
}
-
+
+ .filemgr-tree #txt_rename {
+ margin-left: 21px;
+ }
+
#txt_rename::selection {
background: #90C3EF;
}
View
4 plugins-client/ext.noderunner/noderunner.js
@@ -34,7 +34,7 @@ module.exports = ext.register("ext/noderunner/noderunner", {
ide.addEventListener("socketMessage", this.onMessage.bind(this));
dbg.addEventListener("break", function(e){
- ide.dispatchEvent("break");
+ ide.dispatchEvent("break", e);
});
dbgNode.addEventListener("onsocketfind", function() {
@@ -182,7 +182,7 @@ module.exports = ext.register("ext/noderunner/noderunner", {
// this is a manual action, so we'll tell that to the debugger
dbg.registerManualAttach();
- if (stProcessRunning.active || !stServerConnected.active || typeof path != "string")
+ if (stProcessRunning.active || typeof path != "string")
return false;
stProcessRunning.activate()
View
8 plugins-client/ext.revisions/revisions.js
@@ -831,6 +831,10 @@ module.exports = ext.register("ext/revisions/revisions", {
}
});
break;
+
+ case "serverError":
+ if (console && console.error)
+ console.error("Server error in " + message.body.fromMethod + ": " + message.body.msg);
}
},
@@ -978,7 +982,7 @@ module.exports = ext.register("ext/revisions/revisions", {
var contributors = "";
if (revision.contributors && revision.contributors.length) {
contributors = revision.contributors.map(contributorToXml).join("");
- }
+ }
xmlString += "<contributors>" + contributors + "</contributors></revision>";
return xmlString;
@@ -1502,7 +1506,7 @@ module.exports = ext.register("ext/revisions/revisions", {
ceEditor.$ext.style.right = "0";
var page = tabEditors.getPage();
if (!page) return;
-
+
page.$showRevisions = false;
this.panel.hide();
ide.dispatchEvent("revisions.visibility", { visibility: "hidden" });
View
2  plugins-client/ext.sync/sync.js
@@ -50,7 +50,7 @@ module.exports = ext.register("ext/sync/sync", {
this.lblSyncState = menus.$insertByIndex(barExtras, new apf.label({
"class" : "c9-sync-state-info"
+ (ide.local ? " available-online" : ""),
- "margin" : "4 2 0 0"
+ "margin" : "3 2 0 0"
}), 10),
this.btnSyncStatus = menus.$insertByIndex(barExtras, new apf.button({
id : "btnSync",
View
2  plugins-client/ext.uploadfiles/uploadfiles.js
@@ -475,7 +475,7 @@ module.exports = ext.register("ext/uploadfiles/uploadfiles", {
}
/** Chrome, Firefox */
- if (apf.hasFileApi) {
+ if (window.File && window.FileReader && window.FileList && window.Blob) {
function checkFileExists(exists) {
if (exists) {
if (_self.existingOverwriteAll) {
View
2  plugins-client/lib.ace/www/theme/theme-clouds_midnight.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-clouds-midnight .ace_gutter {\
background: #232323;\
- color: #333;\
+ color: #929292;\
}\
\
.ace-clouds-midnight .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-cobalt.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-cobalt .ace_gutter {\
background: #011e3a;\
- color: #333;\
+ color: #fff;\
}\
\
.ace-cobalt .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-idle_fingers.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-idle-fingers .ace_gutter {\
background: #3b3b3b;\
- color: #333;\
+ color: #fff;\
}\
\
.ace-idle-fingers .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-kr_theme.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-kr-theme .ace_gutter {\
background: #1c1917;\
- color: #333;\
+ color: #FCFFE0;\
}\
\
.ace-kr-theme .ace_print_margin {\
View
4 plugins-client/lib.ace/www/theme/theme-merbivore.js
@@ -49,8 +49,8 @@ exports.cssText = "\
}\
\
.ace-merbivore .ace_gutter {\
- background: #e8e8e8;\
- color: #333;\
+ background: #202020;\
+ color: #E6E1DC;\
}\
\
.ace-merbivore .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-merbivore_soft.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-merbivore-soft .ace_gutter {\
background: #262424;\
- color: #333;\
+ color: #E6E1DC;\
}\
\
.ace-merbivore-soft .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-mono_industrial.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-mono-industrial .ace_gutter {\
background: #1d2521;\
- color: #333;\
+ color: #fff;\
}\
\
.ace-mono-industrial .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-pastel_on_dark.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-pastel-on-dark .ace_gutter {\
background: #353030;\
- color: #333;\
+ color: #8F938F;\
}\
\
.ace-pastel-on-dark .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-tomorrow.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-tomorrow .ace_gutter {\
background: #f6f6f6;\
- color: #333;\
+ color: #4D4D4C;\
}\
\
.ace-tomorrow .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-tomorrow_night.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-tomorrow-night .ace_gutter {\
background: #25282c;\
- color: #333;\
+ color: #C5C8C6;\
}\
\
.ace-tomorrow-night .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-tomorrow_night_bright.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-tomorrow-night-bright .ace_gutter {\
background: #1a1a1a;\
- color: #333;\
+ color: #DEDEDE;\
}\
\
.ace-tomorrow-night-bright .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-tomorrow_night_eighties.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-tomorrow-night-eighties .ace_gutter {\
background: #272727;\
- color: #333;\
+ color: #CCC;\
}\
\
.ace-tomorrow-night-eighties .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-twilight.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-twilight .ace_gutter {\
background: #232323;\
- color: #333;\
+ color: #F8F8F8;\
}\
\
.ace-twilight .ace_print_margin {\
View
2  plugins-client/lib.ace/www/theme/theme-vibrant_ink.js
@@ -50,7 +50,7 @@ exports.cssText = "\
\
.ace-vibrant-ink .ace_gutter {\
background: #1a1a1a;\
- color: #333;\
+ color: white;\
}\
\
.ace-vibrant-ink .ace_print_margin {\
View
20 plugins-client/lib.apf/www/apf-packaged/apf_release.js
@@ -32143,13 +32143,17 @@ apf.BaseTree = function(){
}
if (!this.animation) {
- var diff = apf.getHeightDiff(container),
- oInt = container;
-
- container.style.height = Math.max((height), 0) + "px";
- oInt.scrollTop = oInt.scrollHeight
- - oInt.offsetHeight - diff - (apf.isGecko ? 16 : 0);
- finishSlide();
+ var diff = apf.getHeightDiff(container),
+ oInt = container;
+
+ // This fixes a bug that was introduced in Chrome 20
+ container.style.height = "10px";
+ oInt.scrollTop = 0;
+ // End fix
+ container.style.height = Math.max((height), 0) + "px";
+ oInt.scrollTop = oInt.scrollHeight
+ - oInt.offsetHeight - diff - (apf.isGecko ? 16 : 0);
+ finishSlide();
}
else {
apf.tween.single(container, {
@@ -57518,7 +57522,7 @@ apf.notifier = function(struct, tagName){
};
this.$propHandlers["start-padding"] = function(value) {
- this.startPadding = value;
+ this.startPadding = parseInt(value);
};
this.$propHandlers["timeout"] = function(value) {
View
58 plugins-client/lib.apf/www/apf/elements/codeeditor.js
@@ -69,6 +69,7 @@ apf.codeeditor = module.exports = function(struct, tagName) {
this.$focussable = true; // This object can get the focus
this.$childProperty = "value";
this.$isTextInput = true;
+ this.$activeFrame = null;
this.value = "";
this.multiline = true;
@@ -208,9 +209,14 @@ apf.codeeditor = module.exports = function(struct, tagName) {
doc.setBreakpoints([]);
};
- this.afterOpenFile = function(doc) {
- this.$updateMarker();
+ this.afterOpenFile = function(doc, path) {
this.$updateBreakpoints(doc);
+
+ // if we have a buffered frame with the correct path
+ if (this.$activeFrame && this.$activeFrame.script === path) {
+ // set the marker in this file
+ this.$updateMarker(this.$activeFrame);
+ }
};
this.$clearMarker = function () {
@@ -228,29 +234,21 @@ apf.codeeditor = module.exports = function(struct, tagName) {
return this.$debugger && this.$debugger.$updateMarkerPrerequisite();
};
- this.$updateMarker = function () {
+ this.$updateMarker = function (data) {
this.$clearMarker();
-
- var frame = this.$updateMarkerPrerequisite();
- if (!frame) {
- return;
- }
-
- var script = this.xmlRoot;
- if (script.getAttribute("scriptid") !== frame.getAttribute("scriptid")) {
+
+ if (!data) {
return;
}
+
+ var row = data.line;
- var head = this.$debugger.$mdlStack.queryNode("frame[1]");
- var isTop = frame == head;
- var lineOffset = parseInt(script.getAttribute("lineoffset") || "0", 10);
- var row = parseInt(frame.getAttribute("line"), 10) - lineOffset;
var range = new Range(row, 0, row + 1, 0);
- this.$marker = this.$editor.getSession().addMarker(range, isTop ? "ace_step" : "ace_stack", "line");
- var type = isTop ? "arrow" : "stack";
+ this.$marker = this.$editor.getSession().addMarker(range, "ace_step", "line");
+ var type = "arrow";
this.$lastRow = [row, type];
this.$editor.renderer.addGutterDecoration(row, type);
- this.$editor.gotoLine(row + 1, parseInt(frame.getAttribute("column"), 10), false);
+ this.$editor.gotoLine(row + 1, data.column, false);
};
this.$updateBreakpoints = function(doc) {
@@ -421,8 +419,7 @@ apf.codeeditor = module.exports = function(struct, tagName) {
this.$propHandlers["debugger"] = function(value, prop, inital) {
if (this.$debugger) {
- this.$debugger.removeEventListener("changeframe", this.$onChangeActiveFrame);
- this.$debugger.removeEventListener("break", this.$onChangeActiveFrame);
+ this.$debugger.removeEventListener("break", this.$onBreak);
this.$debugger.removeEventListener("beforecontinue", this.$onBeforeContinue);
}
@@ -446,19 +443,21 @@ apf.codeeditor = module.exports = function(struct, tagName) {
this.$updateMarker();
var _self = this;
- this.$onChangeActiveFrame = function(e) {
- // if you dont have data, we aren't interested in ya
- if (!e || !e.data) {
- return;
- }
-
- _self.$updateMarker();
+ this.$onBreak = function(e) {
+ // buffer the active frame so we can keep track of the marker
+ // when navigating multiple files
+ _self.$activeFrame = e;
+
+ _self.$updateMarker(e);
};
this.$onBeforeContinue = function() {
+ // clear it!
+ _self.$activeFrame = null;
+
_self.$clearMarker();
};
- this.$debugger.addEventListener("changeframe", this.$onChangeActiveFrame);
- this.$debugger.addEventListener("break", this.$onChangeActiveFrame);
+
+ this.$debugger.addEventListener("break", this.$onBreak);
this.$debugger.addEventListener("beforecontinue", this.$onBeforeContinue);
};
@@ -466,7 +465,6 @@ apf.codeeditor = module.exports = function(struct, tagName) {
this.$propHandlers["model"] = function(value) {
propModelHandler.call(this, value);
- this.$updateMarker();
this.$updateBreakpoints();
};
View
27 plugins-client/lib.apf/www/apf/elements/dbg/v8debugger.js
@@ -11,20 +11,35 @@ var V8Debugger = module.exports = function(dbg, host) {
this.$v8breakpoints = {};
var _self = this;
- dbg.addEventListener("changeRunning", function(e) {
+
+ function onChangeRunning (e) {
_self.dispatchEvent("changeRunning", e);
if (dbg.isRunning()) {
_self.setFrame(null);
}
- });
- dbg.addEventListener("break", function(e) {
+ }
+
+ function onBreak (e) {
_self.dispatchEvent("break", e);
- });
- dbg.addEventListener("afterCompile", function(e) {
+ }
+
+ function onAfterCompile (e) {
_self.dispatchEvent("afterCompile", {script: apf.getXml(_self.$getScriptXml(e.data.script))});
- });
+ }
+
+ // register event listeners
+ dbg.addEventListener("changeRunning", onChangeRunning);
+ dbg.addEventListener("break", onBreak);
+ dbg.addEventListener("afterCompile", onAfterCompile);
this.setFrame(null);
+
+ // on detach remove all event listeners
+ this.addEventListener("detach", function () {
+ dbg.removeEventListener("changeRunning", onChangeRunning);
+ dbg.removeEventListener("break", onBreak);
+ dbg.removeEventListener("afterCompile", onAfterCompile);
+ });
};
(function() {
View
195 plugins-client/lib.apf/www/apf/elements/debugger.js
@@ -78,6 +78,16 @@ apf.dbg = module.exports = function(struct, tagName){
this.$debugger.setFrame(value);
this.$ignoreFrameEvent = false;
}
+
+ // if we have a frame, emit a break event
+ if (value) {
+ this.dispatchEvent("break", {
+ column: Number(value.getAttribute("column")),
+ line: Number(value.getAttribute("line")),
+ script: value.getAttribute("script")
+ });
+ }
+
this.dispatchEvent("changeframe", {data: value});
};
@@ -96,69 +106,117 @@ apf.dbg = module.exports = function(struct, tagName){
this.autoAttachComingIn = false;
};
+ /**
+ * Attach the debugger to the IDE
+ */
this.attach = function(host, tab) {
var _self = this;
host.$attach(this, tab, function(err, dbgImpl) {
+ if (err) {
+ return console.error("Attaching console failed", err);
+ }
+
_self.$host = host;
_self.$debugger = dbgImpl;
-
- // give debugger time to initialize
- setTimeout(function() {
- if (!_self.$debugger)
- return;
-
+
+ // do some stuff after attaching and get the currently active frame
+ var afterAttachStep = function (callback) {
+ // load something?
_self.$loadSources(function() {
+ // sync the breakpoints that we have in the IDE with the server
dbgImpl.setBreakpoints(_self.$mdlBreakpoints, function() {
+ // do a backtrace
var backtraceModel = new apf.model();
backtraceModel.load("<frames></frames>");
-
+
+ // and if we find something
_self.$debugger.backtrace(backtraceModel, function() {
var frame = backtraceModel.queryNode("frame[1]");
- var allowAttach = _self.$allowAttaching(frame);
-
- if (!allowAttach) {
- _self.$debugger.continueScript();
- }
- else {
- _self.$mdlStack.load(backtraceModel.data);
- // throw out a nice break statement so others know that it fired
- _self.dispatchEvent("break");
- }
-
- dbgImpl.addEventListener("afterCompile", _self.$onAfterCompile.bind(_self));
-
- _self.$stAttached.activate();
- _self.$stRunning.setProperty("active", dbgImpl.isRunning());
-
- dbgImpl.addEventListener("changeRunning", _self.$onChangeRunning.bind(_self));
- dbgImpl.addEventListener("break", _self.$onBreak.bind(_self));
- dbgImpl.addEventListener("detach", _self.$onDetach.bind(_self));
-
- // monitor the first incoming event to verify whether it's allowed
- // to attach here
- var firstChangeFrame = function () {
- if (_self.$allowAttaching(_self.$debugger.getActiveFrame())) {
- _self.$onChangeFrame();
- // now bind to the real changeFrame method
- dbgImpl.addEventListener("changeFrame", _self.$onChangeFrame.bind(_self));
- dbgImpl.removeEventListener("changeFrame", firstChangeFrame);
- }
- };
- dbgImpl.addEventListener("changeFrame", firstChangeFrame);
-
- if (allowAttach) {
- _self.setProperty("activeframe", frame);
- }
-
- _self.autoAttachComingIn = false;
+
+ // send some info about the current frame in the callback
+ callback(frame, backtraceModel);
});
});
- })
- }, 1000);
- })
+ });
+ };
+
+ // register regular break and changeRunning events
+ var registerEvents = function () {
+ dbgImpl.addEventListener("break", _self.$onBreak.bind(_self));
+ dbgImpl.addEventListener("changeRunning", _self.$onChangeRunning.bind(_self));
+ };
+
+ // function called when we're doing an attach to a new process we just started
+ var newProcess = function () {
+ // the node.js debugger works that we need to wait for the
+ // first breakpoint to be hit, this probably works differently
+ // for other sources, but we'll see about that
+ var onFirstBreak = function (ev) {
+ afterAttachStep(function (frame, stackModel) {
+ var hasBreakpointOnThisFrame = _self.$allowAttaching(frame);
+ if (hasBreakpointOnThisFrame) {
+ // the line we broke on has an actual breakpoint
+ // so let's break on it then
+ _self.$onBreak(ev, stackModel);
+ // and call the changeRunning as well
+ _self.$onChangeRunning();
+ }
+ else {
+ // otherwise step to the next breakpoint
+ _self.continueScript();
+ }
+
+ // remove this listener
+ dbgImpl.removeEventListener("break", onFirstBreak);
+
+ // add the actual listeners for changeRunning & break
+ registerEvents();
+ });
+ };
+
+ dbgImpl.addEventListener("break", onFirstBreak);
+ };
+
+ // re-attach to an already running process
+ var existingProcess = function () {
+ afterAttachStep(function (frame, stackModel) {
+ // send out a break statement for this frame
+ if (frame) {
+ _self.$onBreak({
+ data: {
+ sourceColumn: Number(frame.getAttribute("column")),
+ sourceLine: Number(frame.getAttribute("line")),
+ script: {
+ name: frame.getAttribute("script")
+ }
+ }
+ }, stackModel);
+
+ // make sure we register break events and such
+ registerEvents();
+ }
+ });
+ };
+
+ // depending on this flag we'll call either of these functions
+ if (_self.autoAttachComingIn) {
+ existingProcess();
+ }
+ else {
+ newProcess();
+ }
+
+ // afterCompile and detach handlers are perfectly fine here
+ dbgImpl.addEventListener("afterCompile", _self.$onAfterCompile.bind(_self));
+ dbgImpl.addEventListener("detach", _self.$onDetach.bind(_self));
+ });
};
+
+ this.$attachFreshProcess = function () {
+
+ };
this.$allowAttaching = function (frame) {
var _self = this;
@@ -185,32 +243,41 @@ apf.dbg = module.exports = function(struct, tagName){
this.$onChangeRunning = function() {
var isRunning = this.$debugger && this.$debugger.isRunning();
- if (this.$stRunning.active && !isRunning)
- this.$onBreak();
-
this.$stRunning.setProperty("active", isRunning);
-
- //if (isRunning)
- //this.$mdlStack.load("<frames />");
};
- this.$onBreak = function() {
+ this.$onBreak = function(e, stackModel) {
var _self = this;
- if (!this.$debugger || this.$debugger.isRunning())
- return;
-
- this.$debugger.backtrace(this.$mdlStack, function() {
- if (_self.activeframe && !_self.$updateMarkerPrerequisite()) {
- _self.continueScript();
- return;
- }
- _self.dispatchEvent("break");
- });
+
+ var script = e.data.script.name;
+ if (e.currentTarget && e.currentTarget.stripPrefix) {
+ script = script.indexOf(e.currentTarget.stripPrefix) === 0 ?
+ script.substr(e.currentTarget.stripPrefix) :
+ script;
+ }
+
+ var emit = function () {
+ _self.setProperty("activeframe", _self.$mdlStack.queryNode("frame[1]"));
+ // the active frame change will call the break itself
+ };
+
+ // if we've got the model passed in, it's fine
+ if (stackModel) {
+ _self.$mdlStack.load(stackModel.data.xml);
+ emit();
+ }
+ // otherwise do a backtrace first
+ else {
+ _self.$debugger.backtrace(_self.$mdlStack, function () {
+ emit();
+ });
+ }
};
this.$updateMarkerPrerequisite = function () {
return this.activeframe;
};
+
this.$onAfterCompile = function(e) {
var id = e.script.getAttribute("id");
var oldNode = this.$mdlSources.queryNode("//file[@id='" + id + "']");
View
59 plugins-server/cloud9.core/ide-plugin.js
@@ -2,6 +2,8 @@ var assert = require("assert");
var utils = require("connect").utils;
var error = require("http-error");
var IdeServer = require("./ide");
+var parseUrl = require("url").parse;
+var middleware = require("./middleware");
module.exports = function setup(options, imports, register) {
@@ -17,7 +19,7 @@ module.exports = function setup(options, imports, register) {
var baseUrl = options.baseUrl || "";
var staticPrefix = imports.static.getStaticPrefix();
var workerPrefix = imports.static.getWorkerPrefix() || "/static";
-
+
var socketUrl = options.socketUrl || "/socket.io";
var ide;
@@ -71,30 +73,37 @@ module.exports = function setup(options, imports, register) {
local: options.local
});
- hub.on("ready", function() {
- ide.init(serverPlugins);
-
- connect.useAuth(baseUrl, function(req, res, next) {
- if (!(req.session.uid || req.session.anonid))
- return next(new error.Unauthorized());
- // NOTE: This gets called multiple times!
-
- var pause = utils.pause(req);
-
- initUserAndProceed(req.session.uid || req.session.anonid, ide.options.workspaceId, function(err) {
- if (err) {
- next(err);
- pause.resume();
- return;
- }
- ide.handle(req, res, next);
+ var server = connect.getModule()();
+ connect.useAuth(baseUrl, server);
+
+ server.use(function(req, res, next) {
+ req.parsedUrl = parseUrl(req.url);
+
+ if (!(req.session.uid || req.session.anonid))
+ return next(new error.Unauthorized());
+ // NOTE: This gets called multiple times!
+
+ var pause = utils.pause(req);
+
+ initUserAndProceed(req.session.uid || req.session.anonid, ide.options.workspaceId, function(err) {
+ if (err) {
+ next(err);
pause.resume();
- });
+ return;
+ }
+
+ next();
+ pause.resume();
});
-
+ });
+
+ hub.on("ready", function() {
+ ide.init(serverPlugins);
+ server.use(ide.handle.bind(ide));
+ server.use(middleware.errorHandler());
log.info("IDE server initialized. Listening on " + connect.getHost() + ":" + connect.getPort());
});
-
+
register(null, {
ide: {
register: function(name, plugin, callback) {
@@ -108,9 +117,17 @@ module.exports = function setup(options, imports, register) {
getSocketUrl: function() {
return socketUrl;
},
+ getBaseUrl: function() {
+ return baseUrl;
+ },
getWorkspaceId: function() {
return ide.options.workspaceId.toString();
},
+ use: function(route, handle) {
+ var last = server.stack.pop();
+ server.use(route, handle);
+ server.stack.push(last);
+ },
canShutdown: ide.canShutdown.bind(ide),
initUserAndProceed: initUserAndProceed,
on: ide.on.bind(ide),
View
27 plugins-server/cloud9.core/ide.js
@@ -6,7 +6,6 @@
"use strict";
var assert = require("assert");
-var connect = require("connect");
var User = require("./user");
var fs = require("fs");
var util = require("util");
@@ -32,7 +31,7 @@ var Ide = module.exports = function(options) {
this.workspaceDir = options.workspaceDir;
options.plugins = options.plugins || [];
-
+
this.options = {
workspaceDir: this.workspaceDir,
mountDir: options.mountDir || this.workspaceDir,
@@ -62,13 +61,6 @@ var Ide = module.exports = function(options) {
this.nodeCmd = options.exec || process.execPath;
this.workspace = new Workspace(this);
-
- var _self = this;
- this.router = connect.router(function(app) {
- app.get(/^(\/|\/index.html?)$/, function(req, res, next) {
- _self.$serveIndex(req, res, next);
- });
- });
};
util.inherits(Ide, EventEmitter);
@@ -87,7 +79,10 @@ util.inherits(Ide, EventEmitter);
};
this.handle = function(req, res, next) {
- this.router(req, res, next);
+ if (req.method == "GET" && req.parsedUrl.pathname.match(/^(\/|\/index.html?)$/))
+ this.$serveIndex(req, res, next);
+ else
+ next();
};
this.$serveIndex = function(req, res, next) {
@@ -103,7 +98,7 @@ util.inherits(Ide, EventEmitter);
"cache-control": "no-transform",
"Content-Type": "text/html"
});
-
+
var permissions = _self.getPermissions(req);
var plugins = c9util.arrayToMap(_self.options.plugins);
var bundledPlugins = c9util.arrayToMap(_self.options.bundledPlugins);
@@ -159,10 +154,10 @@ util.inherits(Ide, EventEmitter);
local: _self.options.local,
loadedDetectionScript: loadedDetectionScript
};
-
+
var settingsPlugin = _self.workspace.getExt("settings");
var user = _self.getUser(req);
-
+
if (!settingsPlugin || !user) {
index = template.fill(index, replacements);
res.end(index);
@@ -232,13 +227,13 @@ util.inherits(Ide, EventEmitter);
this.getPermissions = function(req) {
var user = this.getUser(req);
-
+
if (!user)
return User.VISITOR_PERMISSIONS;
else
return user.getPermissions() || User.VISITOR_PERMISSIONS;
};
-
+
this.hasUser = function(username) {
return !!this.$users[username];
};
@@ -284,7 +279,7 @@ util.inherits(Ide, EventEmitter);
this.dispose = function(callback) {
this.emit("destroy");
-
+
this.workspace.dispose(callback);
};
}).call(Ide.prototype);
View
6 plugins-server/cloud9.core/user.js
@@ -6,11 +6,13 @@ var User = module.exports = function (uid, permissions, data) {
EventEmitter.call(this);
this.uid = uid;
- this.permissions = permissions;
this.data = data;
this.clients = [];
this.last_message_time = new Date().getTime();
- this.$server_exclude = {};
+ this.permissions = permissions || User.VISITOR_PERMISSIONS;
+ this.$server_exclude = this.permissions.server_exclude
+ ? c9util.arrayToMap(this.permissions.server_exclude.split("|"))
+ : {};
};
util.inherits(User, EventEmitter);
View
13 plugins-server/cloud9.fs/dav/permission.js
@@ -34,14 +34,13 @@ util.inherits(Permission, jsDAV_ServerPlugin);
this.checkPermission = function(e, method) {
var permissions = this.handler.server.permissions;
- if (!permissions)
- return e.next();
+ if (typeof permissions == "string") {
+ if (this.READ_METHODS[method] && permissions.indexOf("r") > -1)
+ return e.next();
- if (this.READ_METHODS[method] && permissions.indexOf("r") > -1)
- return e.next();
-
- if (this.WRITE_METHODS[method] && permissions.indexOf("w") > -1)
- return e.next();
+ if (this.WRITE_METHODS[method] && permissions.indexOf("w") > -1)
+ return e.next();
+ }
this.handler.httpResponse.writeHead(403);
this.handler.httpResponse.end("operation not permitted!");
View
49 plugins-server/cloud9.ide.revisions/revisions.js
@@ -69,13 +69,17 @@ require("util").inherits(RevisionsPlugin, Plugin);
var self = this;
if (message.subCommand) {
+ var _error = function(msg) {
+ self.broadcastError(message.subCommand, msg, user);
+ };
+
switch (message.subCommand) {
// Directly save a revision. The revision has been precomputed
// on the client as is merely passed to the server in order to
// save it.
case "saveRevision":
if (!message.path) {
- return console.error("saveRevision: No path sent for the file to save");
+ return _error("No path sent for the file to save");
}
this.savingQueue.push({
@@ -83,14 +87,14 @@ require("util").inherits(RevisionsPlugin, Plugin);
revision: message.revision
}, function(err, revisionInfo) {
if (err) {
- return console.error(err);
+ return _error(err.toString());
}
self.broadcastConfirmSave(message.path, revisionInfo.revision);
if (message.forceRevisionListResponse === true) {
self.getAllRevisions(revisionInfo.absPath, function(_err, revObj) {
if (_err) {
- return console.error(_err);
+ return _error("Error retrieving revisions for file " + revisionInfo.absPath);
}
self.broadcastRevisions.call(self, revObj, user, {
@@ -107,14 +111,13 @@ require("util").inherits(RevisionsPlugin, Plugin);
// in order to get the current file).
case "getRevisionHistory":
if (!message.path) {
- return console.error("getRevisionHistory: No path sent for the file to save");
+ return _error("No path sent for the file");
}
this.getRevisions(message.path, function(err, revObj) {
if (err) {
- return console.error(
- "There was a problem retrieving the revisions" +
- " for the file " + message.path + ":\n", err);
+ return _error("There was a problem retrieving the revisions" +
+ " for the file " + message.path + ":\n" + err);
}
self.broadcastRevisions.call(self, revObj, user, {
@@ -127,8 +130,10 @@ require("util").inherits(RevisionsPlugin, Plugin);
case "getRealFileContents":
fs.readFile(message.path, "utf8", function (err, data) {
- if (err) {
- console.error(err);
+ if (err) {
+ return _error("There was a problem reading the contents for the file " +
+ message.path + ":\n" + err);
+
}
user.broadcast(JSON.stringify({
@@ -143,18 +148,18 @@ require("util").inherits(RevisionsPlugin, Plugin);
case "closeFile":
if (!message.path) {
- return console.error("No path sent for the file to be closed");
+ _error("No path sent for the file to be closed");
}
break;
case "removeRevision":
if (!message.path) {
- return console.error("No path sent for the file to be removed");
+ return _error("No path sent for the file to be removed");
}
var path = this.getRevisionsPath(message.path);
if (message.isFolder === true) {
- fs.rmdir(path, {recursive: true}, function() {});
+ fs.rmdir(path, { recursive: true }, function() {});
}
else {
fs.unlink(path + "." + FILE_SUFFIX);
@@ -163,7 +168,7 @@ require("util").inherits(RevisionsPlugin, Plugin);
case "moveRevision":
if (!message.path || !message.newPath) {
- return console.error("Not enough paths sent for the file to be moved");
+ return _error("Not enough paths sent for the file to be moved");
}
var fromPath = this.getRevisionsPath(message.path);
@@ -181,7 +186,7 @@ require("util").inherits(RevisionsPlugin, Plugin);
var renameFn = function() {
fs.rename(fromPath, toPath, function(err) {
if (err) {
- console.error("There was an error moving " + fromPath + " to " + toPath);
+ _error("There was an error moving " + fromPath + " to " + toPath);
}
});
};
@@ -281,8 +286,6 @@ require("util").inherits(RevisionsPlugin, Plugin);
// Path of the final backup file inside the workspace
var absPath = this.getRevisionsPath(filePath + "." + FILE_SUFFIX);
- // Path to the directory wherein the revisions file stays
- var parentDir = this.getRevisionsPath(Path.dirname(filePath));
var self = this;
// does the revisions file exists?
@@ -421,6 +424,20 @@ require("util").inherits(RevisionsPlugin, Plugin);
}));
};
+ this.broadcastError = function(fromMethod, msg, user) {
+ var receiver = user || this.ide;
+ var data = {
+ type: "revision",
+ subtype: "serverError",
+ body: {
+ fromMethod: fromMethod,
+ msg: msg
+ }
+ };
+
+ receiver.broadcast(JSON.stringify(data));
+ };
+
this.saveSingleRevision = function(path, revision, callback) {
if (!path) {
return callback(new Error("Missing or wrong parameters (path, revision):", path, revision));
View
49 plugins-server/cloud9.ide.run-node/run-node.js
@@ -26,7 +26,7 @@ var NodeRuntimePlugin = function(ide, workspace) {
this.workspaceId = workspace.workspaceId;
this.channel = this.workspaceId + "::node-runtime";
-
+
this.hooks = ["command"];
this.name = name;
this.processCount = 0;
@@ -35,6 +35,8 @@ var NodeRuntimePlugin = function(ide, workspace) {
util.inherits(NodeRuntimePlugin, Plugin);
(function() {
+
+ this.debugInitialized = {};
this.init = function() {
var self = this;
@@ -42,14 +44,23 @@ util.inherits(NodeRuntimePlugin, Plugin);
msg.type = msg.type.replace(/^node-debug-(start|data|exit)$/, "node-$1");
var type = msg.type;
- if (type == "node-start" || type == "node-exit")
+ if (type == "node-start" || type == "node-exit") {
self.workspace.getExt("state").publishState();
+ }
- if (msg.type == "node-start")
+ if (msg.type == "node-start") {
self.processCount += 1;
+ }
- if (msg.type == "node-exit")
+ if (msg.type == "node-exit") {
+ delete self.debugInitialized[msg.pid];
+
self.processCount -= 1;
+ }
+
+ if (msg.type == "node-debug-ready") {
+ self.debugInitialized[msg.pid] = true;
+ }
self.ide.broadcast(JSON.stringify(msg), self.name);
});
@@ -59,7 +70,7 @@ util.inherits(NodeRuntimePlugin, Plugin);
var cmd = (message.command || "").toLowerCase();
if (!(/node/.test(message.runner)))
return false;
-
+
var res = true;
switch (cmd) {
case "run":
@@ -75,10 +86,17 @@ util.inherits(NodeRuntimePlugin, Plugin);
this.$kill(message.pid, message, client);
break;
case "debugnode":
- this.pm.debug(message.pid, message.body, function(err) {});
+ this.pm.debug(message.pid, message.body, function(err) {
+ if (err) {
+ // uncommenting this helps with debugging, but we keep it
+ // commented out for the moment, because it throws at the moment
+ // that you stop the debugger, so we have to fix that some day
+ // console.error("debugnode threw error", err)
+ }
+ });
break;
case "debugattachnode":
- this.$attachDebugCient(message, client)
+ this.$attachDebugCient(message, client);
break;
default:
res = false;
@@ -91,9 +109,20 @@ util.inherits(NodeRuntimePlugin, Plugin);
this.workspace.getExt("state").getState(function(err, state) {
if (err)
return self.error(err, 1, message, client);
-
- if (state.debugClient)
- self.ide.broadcast('{"type": "node-debug-ready"}', self.name);
+
+ if (state.debugClient) {
+ // we will only send out the debug ready information when
+ // the debugger is actually attached
+ // otherwise this will be sent from the node-debug-ready command
+ if (self.debugInitialized[state.debugClient] !== true) {
+ return;
+ }
+
+ self.ide.broadcast(JSON.stringify({
+ type: "node-debug-ready",
+ pid: state.debugClient
+ }), self.name);
+ }
});
};
View
32 plugins-server/cloud9.ide.run-npm-module/run-npm-module.js
@@ -115,19 +115,20 @@ util.inherits(NpmRuntimePlugin, Plugin);
return this.$run(message.argv[1], message.argv.slice(2), message.env || {}, message.version, message, null);
var self = this;
- this.searchAndRunShell(message, function(err, found) {
- if (err || found)
- return cb(err, found);
-
- self.searchForModuleHook(message.command, function(found, filePath) {
- if (!found)
- return cb(null, false);
+ // first try to find a module hook
+ self.searchForModuleHook(message.command, function(found, filePath) {
+ // if not found
+ if (!found) {
+ // then run it on the server via sh
+ self.searchAndRunShell(message, cb);
+ return;
+ }
- if (message.argv.length)
- message.argv.shift();
+ // otherwise execute the bastard!
+ if (message.argv.length)
+ message.argv.shift();
- self.$run(filePath, message.argv || [], message.env || {}, message.version, message, null);
- });
+ self.$run(filePath, message.argv || [], message.env || {}, message.version, message, null);
});
};
@@ -166,17 +167,20 @@ util.inherits(NpmRuntimePlugin, Plugin);
// use resolved command
message.argv[0] = out.split("\n")[0];
-
+
self.pm.spawn("shell", {
command: "sh",
- args: ["-c", message.argv.join(" ")],
cwd: cwd,
extra: message.extra,
encoding: "ascii"
}, self.channel, function(err, pid, child) {
if (err)
return self.error(err, 1, message);
-
+
+ // pipe the original line through to sh
+ child.child.stdin.write(message.line);
+ child.child.stdin.end();
+
self.children[pid] = child;
});
});
View
11 plugins-server/cloud9.ide.shell/shell.js