Skip to content

Commit 1d24dc0

Browse files
committed
unload modules in worker and begin to refactor saved location data
SQUASHED: AUTO-COMMIT-demos-tom-babel-plugin-tracer.js,AUTO-COMMIT-demos-tom-defect-demo-plugin.js,AUTO-COMMIT-demos-tom-plugin-backup.js,AUTO-COMMIT-demos-tom-plugin-explorer-worker.js,AUTO-COMMIT-demos-tom-trace.js,AUTO-COMMIT-demos-tom-wrapAST.js,AUTO-COMMIT-src-components-tools-lively-plugin-explorer.js,AUTO-COMMIT-src-components-tools-lively-plugin-explorer-playground.workspace,AUTO-COMMIT-src-components-tools-plugin-selector.js,AUTO-COMMIT-src-components-tools-plugin-selector-list.json,AUTO-COMMIT-src-components-tools-trace-visualization.js,AUTO-COMMIT-src-external-babel-plugin-locals.js,
1 parent 15fda14 commit 1d24dc0

File tree

9 files changed

+299
-27
lines changed

9 files changed

+299
-27
lines changed

demos/tom/babel-plugin-tracer.js

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,7 @@ export default function({ types: t }) {
2929
}
3030

3131
function location(astNode, state) {
32-
const filename = state.file.opts.filename;
33-
34-
const start = astNode.loc.start;
35-
const end = astNode.loc.end;
36-
37-
const locationObject = {
38-
filename,
39-
startLine: start.line,
40-
startColumn: start.column,
41-
endLine: end.line,
42-
endColumn: end.column
43-
}
44-
45-
const id = Trace.register(locationObject);
32+
const id = Trace.register(astNode, state);
4633

4734
return t.numericLiteral(id);
4835
}
@@ -122,10 +109,25 @@ export default function({ types: t }) {
122109

123110
},
124111
ArrowFunctionExpression(path) {
125-
112+
if(path.node.expression) {
113+
const body = path.get('body');
114+
115+
body.replaceWith(callOnTrace('return', [
116+
location(body.node, this),
117+
body.node
118+
]));
119+
120+
body.insertBefore(callOnTrace('enterFunction', [
121+
location(path.node, this),
122+
t.stringLiteral('anonymous function')
123+
]));
124+
} else {
125+
modifyFunction('anonymous function', path, this);
126+
}
126127
},
127128
"ClassMethod|ObjectMethod"(path) {
128-
const name = path.node.key.name;
129+
const key = path.node.key;
130+
const name = key.value || key.name;
129131
modifyFunction(name, path, this);
130132
},
131133
"FunctionDeclaration|FunctionExpression"(path) {
@@ -143,13 +145,21 @@ export default function({ types: t }) {
143145
]));
144146
},
145147
ForOfStatement(path) {
146-
148+
const iterator = path.get('right');
149+
iterator.replaceWith(callOnTrace('forIterator', [
150+
location(iterator.node, this),
151+
iterator.node
152+
]));
147153
},
148154
ForInStatement(path) {
149-
155+
const keys = path.get('right');
156+
keys.replaceWith(callOnTrace('forKeys', [
157+
location(keys.node, this),
158+
keys.node
159+
]));
150160
},
151161
Conditional(path) {
152-
if (path.node.alreadyVisited) {
162+
if (path.node.alreadyVisited || path.isGenerated()) {
153163
return;
154164
}
155165

@@ -161,12 +171,13 @@ export default function({ types: t }) {
161171
]);
162172

163173
// do not log else ifs
174+
const node = path.node;
164175
if (path.parent.type !== 'IfStatement') {
165176
path.insertBefore(callOnTrace('beginCondition', [
166-
location(path.node, this),
177+
location(node, this),
167178
t.stringLiteral(path.type)
168179
]));
169-
path.insertAfter(callOnTrace('endCondition', [location(path.node, this)]));
180+
path.insertAfter(callOnTrace('endCondition', [location(node, this)]));
170181
}
171182
},
172183

demos/tom/defect-demo-plugin.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default function({ types: t }) {
99
},
1010

1111
AssignmentExpression(path) {
12+
if(path.isGenerated()) {
13+
return;
14+
}
1215
const position = t.numericLiteral(path.node.loc.start.line);
1316
path.insertBefore(position);
1417
}

demos/tom/plugin-backup.js

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import Trace from 'demos/tom/trace.js';
2+
import wrapAST from 'demos/tom/wrapAST.js';
3+
4+
export default function({ types: t }) {
5+
function error(path, message) {
6+
throw path.buildCodeFrameError(message);
7+
}
8+
9+
const returnVisitor = {
10+
ReturnStatement(path, state) {
11+
if (path.node.alreadyVisited) {
12+
return;
13+
}
14+
path.node.alreadyVisited = true;
15+
16+
const returnValue = path.node.argument ? path.node.argument : t.identifier('undefined');
17+
const returnNode = callOnTrace('return', [location(path.node, state), returnValue]);
18+
path.node.argument = returnNode;
19+
}
20+
}
21+
22+
function callOnTrace(methodName, args = [], shouldBeStatement = false) {
23+
let call = t.callExpression(t.memberExpression(t.identifier(Trace.traceIdenifierName), t.identifier(methodName)),
24+
args);
25+
if (shouldBeStatement) {
26+
call = t.expressionStatement(call);
27+
}
28+
return call;
29+
}
30+
31+
function location(astNode, state) {
32+
const id = Trace.register(astNode, state);
33+
34+
return t.numericLiteral(id);
35+
}
36+
37+
function modifyFunction(name, path, state) {
38+
const body = path.get('body');
39+
body.unshiftContainer('body', t.expressionStatement(callOnTrace('enterFunction', [location(path.node, state), t
40+
.stringLiteral(name)
41+
])));
42+
body.pushContainer('body', t.expressionStatement(callOnTrace('leave', [location(path.node, state)])));
43+
path.traverse(returnVisitor, state);
44+
}
45+
46+
function resolveName(callee) {
47+
if (callee.type === 'MemberExpression') {
48+
return resolveName(callee.object) + `.${callee.property.name}`;
49+
} else if (callee.type === 'CallExpression') {
50+
return resolveName(callee.callee);
51+
} else {
52+
return callee.name;
53+
}
54+
}
55+
56+
function nameFromCallExpression(path) {
57+
const callee = path.node.callee;
58+
if (callee.type === 'MemberExpression') {
59+
return resolveName(callee)
60+
} else {
61+
return callee.name || 'anonymous function';
62+
}
63+
}
64+
65+
return {
66+
name: 'tracer',
67+
visitor: {
68+
Program(path) {
69+
// wrapAST(path.node, {notify(){console.log(...arguments)}})
70+
},
71+
CallExpression(path) {
72+
if (path.node.alreadyVisited || path.isGenerated()) {
73+
return;
74+
}
75+
76+
77+
path.node.alreadyVisited = true;
78+
let callee = path.get('callee');
79+
let name;
80+
81+
if (t.isMemberExpression(callee)) {
82+
callee.node.computed = true;
83+
callee = path.get('callee.property');
84+
85+
name = callee.node.name || 'anonymous function';
86+
87+
const aboutToEnter = callOnTrace('aboutToEnter',
88+
[
89+
location(callee.node, this),
90+
t.stringLiteral(name)
91+
]);
92+
callee.replaceWith(t.stringLiteral(name));
93+
callee.insertBefore(aboutToEnter);
94+
return;
95+
} else if (t.isFunctionExpression(callee)) {
96+
name = callee.node.id.name || 'anonymous function';
97+
} else { // identifier or anonymous
98+
name = callee.node.name || 'anonymous function';
99+
}
100+
101+
const aboutToEnter = callOnTrace('aboutToEnter',
102+
[
103+
location(callee.node, this),
104+
t.stringLiteral(name)
105+
]);
106+
107+
callee.insertBefore(aboutToEnter);
108+
109+
110+
},
111+
ArrowFunctionExpression(path) {
112+
if(path.node.expression) {
113+
const body = path.get('body');
114+
115+
body.replaceWith(callOnTrace('return', [
116+
location(body.node, this),
117+
body.node
118+
]));
119+
120+
body.insertBefore(callOnTrace('enterFunction', [
121+
location(path.node, this),
122+
t.stringLiteral('anonymous function')
123+
]));
124+
} else {
125+
modifyFunction('anonymous function', path, this);
126+
}
127+
},
128+
"ClassMethod|ObjectMethod"(path) {
129+
const key = path.node.key;
130+
const name = key.value || key.name;
131+
modifyFunction(name, path, this);
132+
},
133+
"FunctionDeclaration|FunctionExpression"(path) {
134+
const id = path.node.id;
135+
const name = id ? id.name : 'anonymous function';
136+
modifyFunction(name, path, this);
137+
},
138+
Loop(path) {
139+
path.insertBefore(callOnTrace('beginLoop', [location(path.node, this), t.stringLiteral(path.type)]))
140+
path.insertAfter(callOnTrace('endLoop', [location(path.node, this)]))
141+
},
142+
ForStatement(path) {
143+
path.get('body').unshiftContainer('body', callOnTrace('nextLoopIteration', [location(path.node, this),
144+
...path.node.init.declarations.map(declaration => declaration.id)
145+
]));
146+
},
147+
ForOfStatement(path) {
148+
const iterator = path.get('right');
149+
iterator.replaceWith(callOnTrace('forIterator', [
150+
location(iterator.node, this),
151+
iterator.node
152+
]));
153+
},
154+
ForInStatement(path) {
155+
const keys = path.get('right');
156+
keys.replaceWith(callOnTrace('forKeys', [
157+
location(keys.node, this),
158+
keys.node
159+
]));
160+
},
161+
Conditional(path) {
162+
if (path.node.alreadyVisited || path.isGenerated()) {
163+
return;
164+
}
165+
166+
path.node.alreadyVisited = true;
167+
168+
path.node.test = callOnTrace('conditionTest', [
169+
location(path.node.test, this),
170+
path.node.test
171+
]);
172+
173+
// do not log else ifs
174+
const node = path.node;
175+
if (path.parent.type !== 'IfStatement') {
176+
path.insertBefore(callOnTrace('beginCondition', [
177+
location(node, this),
178+
t.stringLiteral(path.type)
179+
]));
180+
path.insertAfter(callOnTrace('endCondition', [location(node, this)]));
181+
}
182+
},
183+
184+
AssignmentExpression(path) {
185+
if (path.isGenerated()) {
186+
return;
187+
}
188+
path.node.right = callOnTrace('assignment', [
189+
location(path.node, this),
190+
t.stringLiteral(resolveName(path.node.left)), path.node.right
191+
]);
192+
}
193+
}
194+
}
195+
}

demos/tom/plugin-explorer-worker.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,29 @@ const enumerationConfig = createTraceID => {
3535
return {plugins: [enumerationPlugin(createTraceID)]}
3636
}
3737

38+
39+
// copied from src/client/lively.js
40+
async function unloadModule(path) {
41+
var normalizedPath = System.normalizeSync(path)
42+
try {
43+
// check, to prevent trying to reloading a module a second time if there was an error #375
44+
if (System.get(normalizedPath)) {
45+
await System.import(normalizedPath).then(module => {
46+
if(module && typeof module.__unload__ === "function") {
47+
module.__unload__();
48+
}
49+
});
50+
}
51+
} catch(e) {
52+
console.log("WARNING: error while trying to unload " + path)
53+
}
54+
System.registry.delete(normalizedPath);
55+
// #Hack #issue in SystemJS babel syntax errors do not clear errors
56+
System['@@registerRegistry'][normalizedPath] = undefined;
57+
delete System.loads[normalizedPath]
58+
}
59+
60+
3861
async function importPlugin(url) {
3962
const module = await System.import(url);
4063
const plugin = module.default;
@@ -118,15 +141,17 @@ self.onmessage = function(msg) {
118141
trace.error(e);
119142
}
120143

121-
122-
// const result = babel.transform(msg.data.source, config);
123144
postMessage({
124145
oldAST: oldASTAsString,
125146
transformedAST: JSON.stringify(result && result.ast),
126147
transformedCode: result && result.code,
127148
trace: JSON.stringify(trace),
128149
locations: Trace.locations
129150
});
151+
152+
for (const url of msg.data.urls) {
153+
unloadModule(url);
154+
}
130155
})
131156
})
132157
}

0 commit comments

Comments
 (0)