Skip to content
This repository has been archived by the owner on Oct 21, 2022. It is now read-only.

WIP: Fix electron freezing #2478

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//deploy/core/node_modules/*
!/deploy/core/node_modules/lighttabledeploy/core/node_modules/lighttable/cljs/
/deploy/core/node_modules/*
!/deploy/core/node_modules/lighttable
/deploy/core/node_modules/clojurescript/cljsDeps/
/target/
/deploy/plugins/
Expand Down
6 changes: 3 additions & 3 deletions deploy/core/LightTable.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
</div>
<div id="wrapper" style="opacity:0;">
</div>
<script src="node_modules/lighttable/util/keyevents.js" type="text/javascript"> </script>
<script src="node_modules/lighttable/util/throttle.js" type="text/javascript"> </script>
<script src="lighttable/util/keyevents.js" type="text/javascript"> </script>
<script src="lighttable/util/throttle.js" type="text/javascript"> </script>
<script type="text/javascript">
var script = document.createElement("script");
script.type = "text/javascript";
script.async = false;
script.src= "node_modules/lighttable/bootstrap.js";
script.src= "lighttable/bootstrap.js";
document.body.appendChild(script);
script.onload = function() {
try {
Expand Down
121 changes: 121 additions & 0 deletions deploy/core/lighttable/background/behaviorsParser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
var opposites = {
"(": ")",
"[": "]",
"{": "}",
")": "(",
"]": "[",
"}": "{"
};

var chars = /[^\s\)\]\}]/;

//{:+ {:app [:foo (:blah "asdf" {:foo 234}) :zomg]}}
//var example = "{:+ {:app [(:lt.objs.style/set-skin \"dark\")\n (:lt.plugins.vim/map-keys {\"-\" \"$\",\n \"0\" \"^\",\n \"<BS>\" \"<PageUp>\",\n \"<Space>\" \"<PageDown>\",\n \"j\" \"gj\",\n \"k\" \"gk\"})\n :lt.objs.intro/show-new-file \n ],\n\n :editor [:lt.plugins.vim/activate-vim\n :lt.objs.editor/no-wrap\n :lt.plugins.rainbow-parens/rainbow-parens\n :lt.plugins.auto-complete/auto-show-on-input\n (:lt.objs.style/set-theme \"ibdknox\")],\n\n :editor.behaviors [:lt.plugins.rainbow-parens/rainbow-parens],\n\n :editor.clj [:lt.plugins.rainbow-parens/rainbow-parens],\n\n :editor.clj.instarepl [:lt.plugins.rainbow-parens/rainbow-parens\n (:lt.objs.langs.clj/print-length 1000)],\n\n :editor.cljs [:lt.plugins.rainbow-parens/rainbow-parens],\n\n :editor.javascript [(:lt.plugins.jshint/jshint-options {:maxparams false})\n :lt.plugins.jshint/on-save],\n\n :editor.keymap [:lt.plugins.rainbow-parens/rainbow-parens],\n\n :editor.markdown [:lt.objs.editor/wrap],\n\n :editor.plaintext [:lt.objs.editor/wrap],\n\n :editor.python [(:lt.objs.style/set-theme \"tomorrow-night\")],\n\n :files [(:lt.objs.files/file-types [{:exts [:wisp],\n :mime \"text/x-clojurescript\",\n :name \"Wisp\",\n :tags [:editor.wisp]}])]},\n\n :- {:app [:lt.objs.intro/show-intro]}}\n";


//{:+ {:app {"a" [:foo]}}}

// parseFlat(new CodeMirror.StringStream("[[:app :foo :bar] [:zomg :baz 234 \"hi how are you?\"]]"));
function parseFlat(stream) {

var state = { level: 0, stack: []};
var errors = [];
var entries = [];
var curEntry;

stream.eatSpace();
while(stream.peek()) {
var ch = stream.next();

if (ch == "\"") {
stream.start = stream.pos - 1;
state.mode = "string";
var pos = stream.pos;
var next, escaped = false;
while ((next = stream.next()) != null) {
if (next == "\"" && !escaped) {

state.mode = false;
break;
}
escaped = !escaped && next == "\\";
}

if(state.level === 2) {
curEntry.tokens.push({start: stream.start, end: stream.pos, value: stream.current(), type: "string"});
}

} else if (ch == ";") { // comment
stream.skipTo("\n"); // rest of the line is a comment

} else if (ch == "(" || ch == "[" || ch == "{") {
state.stack.push({type: ch, pos: stream.pos});
state.level++;
if(state.level === 2) {
curEntry = {start: stream.pos - 1,
tokens: []};
entries.push(curEntry);
} else if(state.level === 3) {
curEntry.tokens.push({start: stream.pos - 1,
type: "collection",
tokens: []});
} else if(state.level === 4) {
var lastToken = curEntry.tokens[curEntry.tokens.length - 1];
lastToken.tokens.push({start: stream.pos - 1,
type: "collection",
tokens: []});
}

} else if (ch == ")" || ch == "]" || ch == "}") {
if(state.stack.length && state.stack[state.stack.length - 1].type == opposites[ch]) {
state.stack.pop();
state.level--;

if(state.level === 1) {
curEntry.end = stream.pos;
} else if(state.level === 2) {
curEntry.tokens[curEntry.tokens.length - 1].end = stream.pos;
stream.start = stream.pos;
} else if(state.level === 3) {
var lastToken = curEntry.tokens[curEntry.tokens.length - 1];
lastToken.tokens[lastToken.tokens.length - 1].end = stream.pos;
stream.start = stream.pos;
}

} else {
var expected = "the end of the file";
if(state.stack[state.stack.length - 1]) {
var expected = opposites[state.stack[state.stack.length - 1].type];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'expected' is already defined.

}
errors.push({error: "Unmatched delimiter " + ch + " expected to see " + expected + "", from: stream.start, to: stream.pos});
}


} else if ( ch == ":" ) {
stream.start = stream.pos - 1;
stream.eatWhile(chars);
if(state.level === 2) {
curEntry.tokens.push({start: stream.start, end: stream.pos, value: stream.current(), type: "keyword"});
} else if(state.level === 3) {
var lastToken = curEntry.tokens[curEntry.tokens.length - 1];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'lastToken' is already defined.

lastToken.tokens.push({start: stream.start, end: stream.pos, value: stream.current(), type: "keyword"});
}
stream.start = stream.pos;
} else if(ch.match(chars)) {
stream.start = stream.pos - 1;
var pos = stream.pos;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'pos' is already defined.

stream.eatWhile(chars);
if(state.level === 2) {
curEntry.tokens.push({start: stream.start, end: stream.pos, value: stream.current(), type: "atom"});
} else if(state.level === 3) {
var lastToken = curEntry.tokens[curEntry.tokens.length - 1];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'lastToken' is already defined.

lastToken.tokens.push({start: stream.start, end: stream.pos, value: stream.current(), type: "keyword"});
}
stream.start = stream.pos;
}
}

return {errors: errors, entries: entries};
}

exports.parseFlat = parseFlat;
50 changes: 50 additions & 0 deletions deploy/core/lighttable/background/threadworker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
var fs = require("fs");
var funcs = {};
var ltpath = "";

var _send = function(obj, msg, res, format) {
format = format || "json";
process.send({msg: cljs.core.name(msg), res: res, obj:obj, format: format});
};

var argsArray = function(args) {
var final = [];
for(var i = 0; i < args.length; i++) {
final.push(args[i]);
}
return final;
};

var lttools = {
watch: function(exp, meta) {
_send(meta.obj, cljs.core.keyword(meta.ev), cljs.core.pr_str(cljs.core.js__GT_clj({result: exp, meta: meta}, cljs.core.keyword("keywordize-keys"), true)), "clj");
}
};

process.on("message", function(m) {
try {
switch(m.msg) {
case "init":
ltpath = m.ltpath;
global.eval(fs.readFileSync(ltpath + "/core/node_modules/clojurescript/cljsDeps.js").toString());
cljs.core._STAR_print_fn_STAR_ = function(x) {
var final = clojure.string.trim(x);
if(x != "\n") {
console.log(final);
}
};
_send(m.obj, "connect");
break;
case "register":
eval("funcs['" + m.name + "'] = " + m.func);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eval can be harmful.

break;
case "call":
m.params.unshift(m);
funcs[m.name].apply(null, m.params);
break;
}
} catch (e) {
console.error(e.stack);
}
});

75 changes: 75 additions & 0 deletions deploy/core/lighttable/background/walkdir2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
var fs = require('fs');
var _path = require('path');

var curtime = function() {
return (new Date()).getTime();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.


var walk = function(path,options){

var start = curtime();
var allPaths = [];
if(path.push) {
var queue = path;
} else {
var queue = [path];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'queue' is already defined.

}
var stat = null;
var children = null;
var child = null;
var isDir = null;
var filter = options.filter;
var limit = options.limit;
var cur = null;
var limited = false;
var basename = null;

while(cur = queue.shift()) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'queue' used out of scope.
Expected a conditional expression and instead saw an assignment.


try {
children = fs.readdirSync(cur);
} catch(e) {
console.error("Couldn't read dir " + cur);
continue;
}

for(var i = 0; i < children.length; i++) {
basename = children[i];
child = _path.join(cur, basename);
try {
stat = fs.statSync(child);
} catch(e) {
try {
stat = fs.lstatSync(child);
} catch(e) {
continue;
}
}
isDir = stat.isDirectory();

if(isDir) {
basename += _path.sep;
}

if(!filter || !basename.match(filter)) {
if(isDir) {
queue.push(child);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'queue' used out of scope.

} else if(!limit || allPaths.length <= limit) {
allPaths.push(child);
} else {
queue = [];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'queue' used out of scope.

limited = true;
break;
}
}
}
}

return {time: curtime() - start,
paths: allPaths,
total: allPaths.length,
limited: limited};

}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.


module.exports = walk;
110 changes: 110 additions & 0 deletions deploy/core/lighttable/browserInjection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
(function(window) {

const ipcRenderer = require("electron");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).


function toArray(arrayLike) {
var final = [];
for(var i = 0, len = arrayLike.length; i < len; i++) {
final.push(arrayLike.item(i));
}
return final;
}

ipcRenderer.on("editor.eval.css", function(args) {
var nodeName = args.name.replace(/\./, "-");
var code = args.code;
var styleElem = document.createElement("style");
styleElem.type = "text/css"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.

styleElem.id = nodeName;
styleElem.innerHTML = code;
var prev = document.getElementById(nodeName);
if(prev) {
prev.parentNode.removeChild(prev);
} else {
var link = toArray(document.head.querySelectorAll("link")).filter(function(cur) {
return cur.href.indexOf(args.name) > -1;
});
if(link[0]) {
link[0].parentNode.removeChild(link[0]);
}
}
document.head.appendChild(styleElem);
});


ipcRenderer.on("editor.eval.cljs.exec", function(args) {
for(var i = 0; i < args.results.length; i++) {
var data = args.results[i];
var meta = args.results[i].meta;
meta.verbatim = true;
try {
var res = eval.call(window, args.results[i].code);
if(window.cljs) {
ipcRenderer.sendToHost("browser-raise", [args.client, "editor.eval.cljs.result", {result: cljs.core.pr_str(res), meta: meta}]);
} else {
ipcRenderer.sendToHost("browser-raise", [args.client, "editor.eval.cljs.result", {result: safeStringify(res), meta: meta}]);
}
} catch (e) {
var exdata = cljs.core.ex_data(e);
var error = "";
if (exdata) {
error = e.message + ": " + cljs.core.pr_str(exdata);
} else {
error = cljs.core.pr_str(e);
}

if(e.stack) {
error += "\n" + e.stack;
}
ipcRenderer.sendToHost("browser-raise", [args.client, "editor.eval.cljs.exception", {ex: error, meta: meta}]);
}
}
});

window.addEventListener("hashchange", function(e) {
ipcRenderer.sendToHost("browser-event", ["hashchange", {href: window.location.href, hash: window.location.hash}]);
});

function replacer(key, value) {
if(window.jQuery && value instanceof jQuery) {
return "[jQuery $(" + value.selector + ")]";
}
if(value instanceof Element) {
return "[Element " + value.tagName.toLowerCase() + (value.id != "" ? "#" : "") + value.id + "]";
}
if(value instanceof Array) {
return value;
}
if(typeof(value) == "object") {
if(cache.indexOf(value) > -1) {
return "circular";
}
cache.push(value);
return value;
}
if(typeof value == "function") {
return "[function]";
}
return value;
}

function safeStringify(res) {
cache = [];
return JSON.stringify(res, replacer);
}

window.lttools = {
watch: function(exp, meta) {
if(meta.ev == "editor.eval.cljs.watch") {
var final = cljs.core.pr_str(exp);
} else {
meta["no-inspect"] = true;
var final = safeStringify(exp);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'final' is already defined.

}
ipcRenderer.sendToHost("browser-raise", [meta.obj, meta.ev, {result: final, meta: meta}]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'final' used out of scope.

return exp;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.



})(window);