Skip to content

Commit a7d893d

Browse files
committed
Merge branch 'gh-pages' of https://github.com/LivelyKernel/lively4-core into gh-pages
2 parents 41b8ef2 + d75d87e commit a7d893d

29 files changed

+11421
-281
lines changed

demos/tom/TraceLogParser.js

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ export default class TraceLogParser {
1212
constructor(trace) {
1313
this.trace = trace;
1414
this.index = 0;
15-
16-
this.functionNesting = 0;
17-
this.conditionNesting = 0;
1815
}
1916

2017
get log() {
@@ -76,13 +73,13 @@ export default class TraceLogParser {
7673
if(this.match('leavePlugin')) {
7774
return section;
7875
} else if(this.matchPeek('return')) {
79-
// Todo: escape nested constructs, ie function(condition(return))
8076
const returnEntry = this.consume();
8177
section.addEntry(this.instantiateEvent(returnEntry));
8278

8379
if(returnEntry.position === this.peek().position) {
8480
this.match('left');
8581
}
82+
debugger
8683

8784
throw new EarlyReturn('function');
8885
} else if(this.matchPeek('leave')) {
@@ -123,18 +120,10 @@ export default class TraceLogParser {
123120
section.addEntry(this.consumeAsEvent());
124121
// break out from nesting
125122
throw new EarlyReturn('error');
126-
}
127-
128-
if(this.conditionNesting > 0) {
129-
if(this.match('endCondition')) {
130-
return section;
131-
}
132-
}
133-
134-
if(this.functionNesting > 0) {
135-
if(this.match('left')) {
136-
return section;
137-
}
123+
} else if(this.match('endCondition')) {
124+
return section;
125+
} else if(this.match('left')) {
126+
return section;
138127
}
139128

140129
section.addEntry(this.consumeAsEvent());
@@ -150,9 +139,7 @@ export default class TraceLogParser {
150139

151140
section.addEntry(condition);
152141

153-
this.conditionNesting++;
154142
this.defaultParse(condition, higherSections);
155-
this.conditionNesting--;
156143

157144
return condition;
158145
}
@@ -168,9 +155,6 @@ export default class TraceLogParser {
168155

169156
section.addEntry(fun);
170157

171-
const oldNestingLevel = this.conditionNesting;
172-
this.functionNesting++;
173-
174158
try {
175159
this.defaultParse(fun, higherSections);
176160
} catch(e) {
@@ -181,10 +165,6 @@ export default class TraceLogParser {
181165
}
182166
}
183167

184-
// restore condition nesting level as we maybe escaped from one without properly doing so
185-
this.conditionNesting = oldNestingLevel;
186-
this.functionNesting--;
187-
188168
return fun;
189169
}
190170

demos/tom/copyAST.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ function copyArrayOfRound(arr, roundNumber) {
88
return copy;
99
}
1010

11+
// Todo: merge wrap and copy => copy all nodes without traceID
12+
// roundNumber could result in unncessary copies as in one round there could be multiple edits
1113
export default function copyASTPartsOfRound(object, roundNumber) {
1214
// simply check if the object is an astNode
1315
if (object && object.type) {
@@ -37,7 +39,6 @@ export default function copyASTPartsOfRound(object, roundNumber) {
3739
// ignore functions
3840
break;
3941
case 'object':
40-
// assume it is an astNode
4142
objectCopy[key] = copyASTPartsOfRound(value, roundNumber);
4243
break;
4344
default:

demos/tom/index.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
1-
Todo: write
1+
2+
## AST worker
3+
Der AST worker nimmt source code und ein Array von Plugin Urls entgegen und generiert aus diesen einen Trace der Ausführung. Dieser Prozess wurde in eine WebWorker ausgelagert, um eine frische JavaScript Umgebung zu erhalten. Normalerweise hat lively ein vorkonfiguriertes SystemJS, welches sich um imports von Files kümmert. Im WebWorker kann SystemJS so konfiguriert werden, dass nur das Trace Plugin auf allen importierten Code angewandt wird (wodurch auch imports von Plugins mit dem nötigen Trace code versehen werden).
4+
5+
## Trace
6+
Trace ist die zentrale Klasse, für welche während der gesamten Aufzeichnung der Plugins sichergestellt ist, dass sie global über ```window[Trace.traceIdentifierName]``` verfügbar ist.
7+
8+
Ihre Aufgabe ist es zum einen den Tracelog zu generieren und zu speichern. Dazu stellt die Klasse Methode bereit, die die nötigen Instanzen von ```Event```, ```ErrorEvent``` oder ```ASTChangeEvent``` mit den nötigen Daten erstellen.
9+
10+
Auch erstellt der Trace die IDs für AST Knoten, die aus der Nummer der aktuell ausgeführten Pluginmethode (leider nur der aus den Babelplugins und nicht den in ```NodePath.traverse``` aufgerufenden Methoden) und einer für den gesamten AST globalen Nummer.
11+
12+
Trace registriert weiterhin die Positionen von AST Knoten im Quelltext und speichert diese mit einigen Optimierungen. Die dadurch vergebenen Positions-IDs kann Trace auh wieder auflösen.
13+
14+
## Events
15+
16+
## TraceLogParser
17+
Der ```TraceLogParser``` ist ein recursive Descent Parser, der dafür verantwortlich ist den generierten Log zu säubern und zusammengehörige Events zusammenzufassen. Es erzeugt aus den ```Event```s eine Composite aus ```TraceSection``` und ```Event```s.
218

319

420
## Debug Trace-Plugin
21+
Es ist möglich das tracer-plugin mit sich selbst zu debuggen. Dazu wird einfach eine Kopie des Plugins (aktuell in demos/tom/plugin-backup.js) an den WebWorker übergeben als Plugin übergeben. Die Kopie ist nötig, da SystemJS das tracer-plugin ganz am Anfang laden muss und dies nun gecached vorhält. Würde man versuchen das originale tracer-plugin noch einmal zu laden würde einfach auf diese Version zugegriffen werden, anstatt das Plugin zu transformieren. Dies wird mit diesem Workaround eines zweiten Files umgangen.
22+
23+
**Sollte die Kopie zur Weiterentwicklung verwendet werden, nicht vergessen die gewünschten Änderungen am Ende in das originale Plugin zu kopieren.**
524

625

726
## Future ideas

demos/tom/playground.js

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,14 @@ export default function({types: t}) {
22
return {
33
name: 'test',
44
visitor: {
5-
FunctionDeclaration(path) {
6-
if(path.node.alreadyVisited) {
7-
return;
8-
}
9-
10-
const returnNode = t.returnStatement(t.arrowFunctionExpression([], t.numericLiteral(5)));
11-
12-
const node = t.functionDeclaration(
13-
path.node.id,
14-
[],
15-
t.blockStatement([returnNode]));
16-
node.alreadyVisited = true;
17-
18-
path.replaceWith(node);
5+
Conditional(path) {
6+
debugger
7+
path.get('test').insertAfter(t.stringLiteral('afterTest'));
8+
},
9+
10+
AssignmentExpression(path) {
11+
debugger
12+
path.node.loc.start
1913
}
2014
}
2115
}

demos/tom/plugin-explorer-worker.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ async function unloadModule(path) {
5454
System.registry.delete(normalizedPath);
5555
// #Hack #issue in SystemJS babel syntax errors do not clear errors
5656
System['@@registerRegistry'][normalizedPath] = undefined;
57+
debugger
5758
delete System.loads[normalizedPath]
5859
}
5960

@@ -106,6 +107,10 @@ self.onmessage = function(msg) {
106107
}
107108
});
108109

110+
const preloadedPlugins = new Set(Object.keys(System['@@registerRegistry']));
111+
112+
debugger
113+
109114
const trace = new Trace();
110115
// make it globally available for use in plugins
111116
window[Trace.traceIdentifierName] = trace;
@@ -140,15 +145,20 @@ self.onmessage = function(msg) {
140145
result = null;
141146
trace.error(e);
142147
}
143-
144-
postMessage({
145-
oldAST: oldASTAsString,
146-
transformedAST: JSON.stringify(result && result.ast),
147-
transformedCode: result && result.code,
148-
trace: trace.serialize()
149-
});
150-
151-
msg.data.urls.forEach(unloadModule)
148+
debugger;
149+
150+
const pluginsToUnload = Object.keys(System['@@registerRegistry']).filter(plugin => !
151+
preloadedPlugins.has(plugin));
152+
153+
Promise.all(pluginsToUnload.map(unloadModule))
154+
.then(_ => {
155+
postMessage({
156+
oldAST: oldASTAsString,
157+
transformedAST: JSON.stringify(result && result.ast),
158+
transformedCode: result && result.code,
159+
trace: trace.serialize()
160+
});
161+
})
152162
})
153163
})
154164
}

demos/tom/trace.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as _ from 'src/external/lodash/lodash.js';
22
import loadPlugin from 'demos/tom/plugin-load-promise.js';
3-
import { ErrorEvent, Event, ASTChangeEvent, eventTypes } from 'demos/tom/Events.js';
3+
import { ErrorEvent, Event, ASTChangeEvent } from 'demos/tom/Events.js';
44
import TraceLogParser from 'demos/tom/TraceLogParser.js';
55

66
function clone(object) {

demos/tom/wrapAST.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,13 @@ function createObservingAccessorsOn(object, propertyName, observer) {
2323
const handler = (observer, key) => {
2424
return {
2525
set: function(obj, prop, value) {
26-
// Todo: Reflect.set()
2726
if (Number.isInteger(Number.parseInt(prop))) {
2827
const pluginRound = window[Trace.traceIdentifierName].pluginRound;
29-
debugger
3028
wrapAST(value, observer, true);
3129
observer.notify(prop, copyAST(obj[prop], pluginRound), copyAST(value, pluginRound), key);
3230
}
33-
obj[prop] = value;
34-
return true;
31+
32+
return Reflect.set(obj, prop, value);
3533
}
3634
}
3735
};

src/client/reactive/active-expression/active-expression.js

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ export const AExprRegistry = {
7373
*/
7474
allAsArray() {
7575
return Array.from(self.__aexprRegistry_aexprs__);
76+
},
77+
78+
addEventListener(reference, callback) {
79+
if(!this.listeners) this.listeners = []
80+
this.listeners.push({ reference, callback });
81+
},
82+
83+
eventListeners() {
84+
this.listeners = this.listeners.filter(listener => listener.reference);
85+
return this.listeners;
7686
}
7787
};
7888

@@ -202,7 +212,7 @@ export class BaseActiveExpression {
202212
}
203213

204214
this.initializeEvents();
205-
this.logEvent('created');
215+
this.logEvent('created', this);
206216

207217
if (new.target === BaseActiveExpression) {
208218
this.addToRegistry();
@@ -321,9 +331,8 @@ export class BaseActiveExpression {
321331
const lastValue = this.lastValue;
322332
this.storeResult(value);
323333
this.findCallee().then(trigger => {
324-
this.logEvent('changed value', {value, trigger});
325-
})
326-
334+
this.logEvent('changed value', { value, trigger, lastValue });
335+
});
327336

328337
this.notify(value, {
329338
lastValue,
@@ -335,9 +344,9 @@ export class BaseActiveExpression {
335344
async findCallee() {
336345
const stack = lively.stack();
337346
const frames = stack.frames;
338-
347+
339348
for (let frame of frames) {
340-
if(!frame.file.includes("active-expression") && frame.file !== "<anonymous>") {
349+
if (!frame.file.includes("active-expression") && frame.file !== "<anonymous>") {
341350
return await frame.getSourceLoc();
342351
}
343352
}
@@ -572,7 +581,9 @@ export class BaseActiveExpression {
572581
if (this.isMeta()) return;
573582
//if(!this.meta().has('events'))this.meta({events : new Array()});
574583
let events = this.meta().get('events');
575-
events.push({ timestamp: new Date(), type, value });
584+
const event = { timestamp: new Date(), type, value };
585+
AExprRegistry.eventListeners().forEach(listener => listener.callback(this, event));
586+
events.push(event);
576587
if (events.length > 5000) events.shift();
577588
}
578589

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,56 @@
11
<template id="aexpr-timeline" >
2-
<style data-src="/src/external/font-awesome/css/font-awesome.css"></style>
3-
<style data-src="/templates/livelystyle.css"></style>
4-
<style data-src="/src/client/reactive/components/basic/aexpr-timeline.css"></style>
2+
<style data-src="/src/external/font-awesome/css/font-awesome.css"></style>
3+
<style data-src="/templates/livelystyle.css"></style>
4+
<style data-src="/src/client/reactive/components/basic/aexpr-timeline.css"></style>
5+
<style data-src="/src/external/jstree/themes/default/style.css"></style>
6+
<script src="https://lively-kernel.org/lively4/lively4-markus/src/external/jquery.js"></script>
7+
<script src="https://lively-kernel.org/lively4/lively4-markus/src/external/jstree/jstree.js"></script>
58

6-
<style>
7-
:host {
8-
9-
}
10-
#content {
11-
background-color: gray;
12-
}
13-
</style>
14-
<div id="diagram" style="width: 100%; height: calc(100% - 80px); overflow: auto"></div>
15-
<p class="infos">
16-
<span id="numberEvents"></span> events <span class="light">found between</span> <br />
17-
<span id="zoomStart"></span> <span class="light">and</span> <span id="zoomEnd"></span>
18-
</p>
9+
<style>
10+
:host {
11+
}
12+
#content {
13+
background-color: gray;
14+
}
15+
.container {
16+
display: grid;
17+
grid-template-rows: auto 1fr auto;
18+
align-items:stretch;
19+
justify-items:stretch;
20+
height: 100%;
21+
}
22+
.row {
23+
display: grid;
24+
grid-template-columns: 1fr 1fr;
25+
align-items:stretch;
26+
justify-items:stretch;
27+
width: 100%;
28+
}
29+
.pane {
30+
margin: 1px;
31+
border: 1px solid #d5d5d5;
32+
}
33+
</style>
34+
35+
<div class="container">
36+
<div class="row">
37+
<div id="aeOverview" class="pane"></div>
38+
<div>
39+
Values over time
40+
</div>
41+
</div>
42+
<div id="diagram" class="pane"></div>
43+
<div id="footer" class="pane">
44+
<p class="infos">
45+
<span id="numberEvents"></span> events <span class="light">found between</span> <br />
46+
<span id="zoomStart"></span> <span class="light">and</span> <span id="zoomEnd"></span>
47+
</p>
48+
<center>
49+
<input type="checkbox" id="groupByLine" name="group by line" checked>
50+
<label for="groupByLine"> Group by line </label><br>
51+
</center>
52+
</div>
53+
</div>
1954
<content></content>
2055
</template>
2156

0 commit comments

Comments
 (0)