Skip to content

Commit d32395e

Browse files
committed
fine_granular ast copying
SQUASHED: AUTO-COMMIT-demos-tom-copyAST.js,AUTO-COMMIT-demos-tom-copy.js,AUTO-COMMIT-demos-tom-Events.js,AUTO-COMMIT-demos-tom-playground.js,AUTO-COMMIT-demos-tom-trace.js,AUTO-COMMIT-demos-tom-wrapAST.js,AUTO-COMMIT-src-components-tools-trace-visualization.js,
1 parent acf1d0d commit d32395e

File tree

6 files changed

+106
-68
lines changed

6 files changed

+106
-68
lines changed

demos/tom/Events.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ export class ASTChangeEvent {
5151
}
5252

5353
getNode(id, astNode) {
54-
55-
5654
if (astNode.type) {
5755
const isSearchedNode = value => value && value.traceID !== undefined && value.traceID.nodeID === id.nodeID;
5856

@@ -90,24 +88,49 @@ export class ASTChangeEvent {
9088
if (isSearchedNode(node)) {
9189
return node;
9290
}
93-
// fallthrough as we want to know if a node is replaced
91+
break;
9492
default:
9593
// ignore value
9694
}
9795
}
9896
}
9997
}
98+
99+
resolve(copy, ast) {
100+
101+
// Todo: optimize by caching: traceID -> ASTNode
102+
if(copy.isTraceID) {
103+
return this.getNode(copy, ast);
104+
} else if(Array.isArray(copy)) {
105+
const result = [];
106+
for(const entry of copy) {
107+
result.push(this.resolve(entry, ast));
108+
}
109+
return result;
110+
} else if(copy.traceID) { // is astNode
111+
const result = {};
112+
113+
for(const key in copy) {
114+
// do not expand the reference of the object itself
115+
if(key === 'traceID') {
116+
result[key] = copy[key];
117+
continue;
118+
}
119+
result[key] = this.resolve(copy[key], ast);
120+
}
121+
122+
return result;
123+
} else {
124+
return copy;
125+
}
126+
}
100127

101128
apply(ast) {
102129
let astNode = this.getNode(this.objectID, ast);
103130
if (this.arrayProperty) {
104131
astNode = astNode[this.arrayProperty];
105132
}
106-
astNode[this.propertyName] = this.newValue;
107-
}
108-
109-
revert(ast) {
110-
133+
astNode[this.propertyName] = this.resolve(this.newValue, ast);
111134
}
112135

113136
visit(object) {

demos/tom/copyAST.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
function copyArrayOfRound(arr, roundNumber) {
2+
const copy = [];
3+
4+
for(const entry of arr) {
5+
copy.push(copyASTPartsOfRound(entry, roundNumber));
6+
}
7+
8+
return copy;
9+
}
10+
11+
export default function copyASTPartsOfRound(object, roundNumber) {
12+
// simply check if the object is an astNode
13+
if (object && object.type) {
14+
// if already in AST return only a reference
15+
if (object.traceID && object.traceID.pluginRoundID !== roundNumber) {
16+
return object.traceID;
17+
}
18+
19+
const objectCopy = {};
20+
const keys = Object.keys(object).filter(key => key[0] !== '_');
21+
for (const key of keys) {
22+
const value = object[key];
23+
24+
if (Array.isArray(value)) {
25+
objectCopy[key] = copyArrayOfRound(value, roundNumber);
26+
27+
continue;
28+
}
29+
30+
if (value === null) {
31+
objectCopy[key] = value;
32+
continue;
33+
}
34+
35+
switch (typeof value) {
36+
case 'function':
37+
// ignore functions
38+
break;
39+
case 'object':
40+
// assume it is an astNode
41+
objectCopy[key] = copyASTPartsOfRound(value, roundNumber);
42+
break;
43+
default:
44+
objectCopy[key] = value;
45+
}
46+
}
47+
48+
return objectCopy;
49+
} else {
50+
if(Array.isArray(object)) {
51+
return copyArrayOfRound(object, roundNumber);
52+
} else {
53+
// do a simple copy
54+
return JSON.parse(JSON.stringify(object));
55+
}
56+
}
57+
}

demos/tom/playground.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export default function({types: t}) {
22
return {
33
name: 'test',
44
visitor: {
5-
Function(path) {
5+
FunctionDeclaration(path) {
66
if(path.node.alreadyVisited) {
77
return;
88
}

demos/tom/trace.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ function clone(object) {
1414
export default class Trace {
1515
constructor() {
1616
this._log = [];
17+
1718
this.counter = 0;
19+
this.pluginRound = 0;
1820

1921
this.locations = [];
2022
this.filenames = [];
@@ -32,7 +34,7 @@ export default class Trace {
3234

3335
createTraceID() {
3436
return {
35-
sectionID: 0,
37+
pluginRoundID: this.pluginRound,
3638
nodeID: this.counter++,
3739
isTraceID: true
3840
}
@@ -132,7 +134,7 @@ export default class Trace {
132134
/* AST changes */
133135

134136
notify(objectID, key, oldValue, newValue, arrayProperty) {
135-
const event = new ASTChangeEvent(objectID, key, clone(oldValue), clone(newValue));
137+
const event = new ASTChangeEvent(objectID, key, oldValue, newValue);
136138
this.log(event);
137139
event.arrayProperty = arrayProperty;
138140
}
@@ -141,6 +143,7 @@ export default class Trace {
141143

142144
enterPlugin(name) {
143145
this.log(new Event('enterPlugin', name));
146+
this.pluginRound++;
144147
}
145148

146149
leavePlugin(name) {

demos/tom/wrapAST.js

Lines changed: 10 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import Trace from 'demos/tom/trace.js';
2+
import copyAST from 'demos/tom/copyAST.js';
23

3-
const excludedProperties = ['end', 'loc', 'start', 'traceID', 'type'];
4-
5-
function copy(value) {
6-
return value; // JSON.parse(JSON.stringify(value));
7-
}
4+
export const excludedProperties = ['end', 'loc', 'start', 'traceID', 'type'];
85

96
function createObservingAccessorsOn(object, propertyName, observer) {
107
const newPropertyName = '_' + propertyName;
118
object[newPropertyName] = object[propertyName];
129
Object.defineProperty(object, propertyName, {
1310
get() { return object[newPropertyName]; },
1411
set(value) {
15-
observer.notify(object.traceID, propertyName, object[newPropertyName], value);
12+
const pluginRound = window[Trace.traceIdentifierName].pluginRound;
1613
wrapAST(value, observer, true);
14+
observer.notify(object.traceID,
15+
propertyName,
16+
copyAST(object[newPropertyName], pluginRound),
17+
copyAST(value, pluginRound));
1718
object[newPropertyName] = value;
1819
}
1920
})
@@ -24,8 +25,10 @@ const handler = (observer, key) => {
2425
set: function(obj, prop, value) {
2526
// Todo: Reflect.set()
2627
if (Number.isInteger(Number.parseInt(prop))) {
27-
observer.notify(prop, copy(obj[prop]), copy(value), key);
28+
const pluginRound = window[Trace.traceIdentifierName].pluginRound;
29+
debugger
2830
wrapAST(value, observer, true);
31+
observer.notify(prop, copyAST(obj[prop], pluginRound), copyAST(value, pluginRound), key);
2932
}
3033
obj[prop] = value;
3134
return true;
@@ -37,56 +40,6 @@ function wrappedArray(array, observer, key) {
3740
return new Proxy(array, handler(observer, key));
3841
}
3942

40-
function copyUnknownASTParts(astNode) {
41-
// simply check if the object is an astNode
42-
if (astNode && astNode.type) {
43-
// if already in AST return only a reference
44-
if (astNode.traceID) {
45-
return astNode.traceID;
46-
}
47-
48-
const objectCopy = {};
49-
50-
const keys = Object.keys(astNode).filter(key => !excludedProperties.includes(key));
51-
for (const key of keys) {
52-
const value = astNode[key];
53-
54-
if (Array.isArray(value)) {
55-
const copiedArray = [];
56-
objectCopy[key] = copiedArray;
57-
58-
for(const entry of value) {
59-
copiedArray.push(copyUnknownASTParts(entry));
60-
}
61-
62-
continue;
63-
}
64-
65-
if (value === null) {
66-
objectCopy[key] = value;
67-
continue;
68-
}
69-
70-
switch (typeof value) {
71-
case 'function':
72-
// ignore functions
73-
break;
74-
case 'object':
75-
// assume it is an astNode
76-
objectCopy[key] = copyUnknownASTParts(value);
77-
break;
78-
default:
79-
objectCopy[key] = value;
80-
}
81-
}
82-
83-
return objectCopy;
84-
} else {
85-
// probably not an AST node => do a generic copy
86-
return JSON.parse(JSON.stringify(astNode));
87-
}
88-
}
89-
9043
export default function wrapAST(astNode, observer, onlyUnknownNodes) {
9144
// simply check if the object is an astNode
9245
if (astNode && astNode.type) {

src/components/tools/trace-visualization.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ export default class TraceVisualization extends Morph {
197197
updateAST(path, entry) {
198198
this.curAST = JSON.parse(JSON.stringify(this.trace.oldAST));
199199
this.nextAST;
200+
201+
debugger
200202

201203
let entries = this.trace.sections;
202204

0 commit comments

Comments
 (0)