11import * as _ from 'src/external/lodash/lodash.js' ;
22import loadPlugin from 'demos/tom/plugin-load-promise.js'
33
4+ const excludedProperties = [ 'end' , 'loc' , 'start' , 'traceID' , 'type' ] ;
5+
46class Event {
57 constructor ( type , data , position ) {
68 this . type = type ;
79 this . position = position ;
810 this . data = data ;
9-
11+
1012 this . changes = [ ] ;
1113 this . hasChanges = false ;
12-
14+
1315 this . __type__ = 'Event' ;
1416 }
15-
17+
1618 addChange ( changeEvent ) {
1719 this . hasChanges = true ;
1820 this . changes . push ( changeEvent ) ;
1921 }
20-
22+
23+ apply ( ast ) {
24+ for ( const change of this . changes ) {
25+ change . apply ( ast ) ;
26+ }
27+ }
28+
2129 visit ( object ) {
2230 object . visitEvent ( this ) ;
2331 }
@@ -29,18 +37,70 @@ class ASTChangeEvent {
2937 this . propertyName = propertyName ;
3038 this . oldValue = oldValue ;
3139 this . newValue = newValue ;
32-
40+
3341 this . __type__ = 'ASTChangeEvent' ;
3442 }
35-
36- apply ( ast ) {
43+
44+ getNode ( id , astNode ) {
3745
46+
47+ if ( astNode . type ) {
48+ const isSearchedNode = value => value && value . traceID !== undefined && value . traceID . nodeID === id . nodeID ;
49+
50+ if ( isSearchedNode ( astNode ) ) {
51+ return astNode ;
52+ }
53+
54+ const keys = Object . keys ( astNode ) . filter ( key => ! excludedProperties . includes ( key ) ) ;
55+ for ( const key of keys ) {
56+ const value = astNode [ key ] ;
57+
58+
59+ if ( Array . isArray ( value ) ) {
60+ for ( const entry of value ) {
61+ const node = this . getNode ( id , entry )
62+ if ( isSearchedNode ( node ) ) {
63+ return node ;
64+ }
65+ }
66+
67+ continue ;
68+ }
69+
70+ if ( ! value ) {
71+ continue ;
72+ }
73+
74+ switch ( typeof value ) {
75+ case 'function' :
76+ // ignore functions
77+ break ;
78+ case 'object' :
79+ // assume it is an astNode
80+ const node = this . getNode ( id , value )
81+ if ( isSearchedNode ( node ) ) {
82+ return node ;
83+ }
84+ // fallthrough as we want to know if a node is replaced
85+ default :
86+ // ignore value
87+ }
88+ }
89+ }
3890 }
39-
91+
92+ apply ( ast ) {
93+ let astNode = this . getNode ( this . objectID , ast ) ;
94+ if ( this . arrayProperty ) {
95+ astNode = astNode [ this . arrayProperty ] ;
96+ }
97+ astNode [ this . propertyName ] = this . newValue ;
98+ }
99+
40100 revert ( ast ) {
41-
101+
42102 }
43-
103+
44104 visit ( object ) {
45105 object . visitASTChangeEvent ( this ) ;
46106 }
@@ -63,30 +123,44 @@ class TraceSection {
63123 constructor ( name , entries = [ ] ) {
64124 this . name = name ;
65125 this . entries = entries ;
66-
126+
67127 this . nodes = new Map ( ) ;
68-
128+
69129 this . changes = [ ] ;
70130 this . hasChanges = false ;
71131 }
72132
73133 addEntry ( entry ) {
74134 this . entries . push ( entry ) ;
75135 }
76-
136+
77137 addChange ( changeEvent ) {
78138 this . hasChanges = true ;
79- if ( this . entries . last ) {
139+ if ( this . entries . last ) {
80140 this . entries . last . addChange ( changeEvent ) ;
141+ } else {
142+ const stub = new Event ( 'stub' ) ;
143+ this . entries . push ( stub ) ;
144+ stub . addChange ( changeEvent ) ;
81145 }
82146 this . changes . push ( changeEvent ) ;
83-
147+
84148 }
85-
149+
86150 somethingHappened ( ) {
87151 return this . hasChanges || this . entries . length > 0 ;
88152 }
89-
153+
154+ apply ( ast ) {
155+ for ( const change of this . changes ) {
156+ change . apply ( ast ) ;
157+ }
158+ }
159+
160+ revert ( ast ) {
161+
162+ }
163+
90164 visit ( object ) {
91165 object . visitTraceSection ( this ) ;
92166 }
@@ -109,18 +183,20 @@ class Trace {
109183 startTraversion ( ) {
110184 this . log ( new Event ( 'startTraversion' ) ) ;
111185 }
112-
186+
113187 createTraceID ( ) {
114188 return {
115- sectionId : 0 ,
116- nodeId : this . counter ++
189+ sectionID : 0 ,
190+ nodeID : this . counter ++
117191 }
118192 }
119193
120194 /* AST changes */
121195
122- notify ( objectID , key , oldValue , newValue ) {
123- this . log ( new ASTChangeEvent ( objectID , key , clone ( oldValue ) , clone ( newValue ) ) ) ;
196+ notify ( objectID , key , oldValue , newValue , arrayProperty ) {
197+ const event = new ASTChangeEvent ( objectID , key , clone ( oldValue ) , clone ( newValue ) ) ;
198+ this . log ( event ) ;
199+ event . arrayProperty = arrayProperty ;
124200 }
125201
126202 /* Plugins */
@@ -188,13 +264,13 @@ class Trace {
188264 this . log ( new Event ( 'assignment' , [ clone ( left ) , clone ( right ) ] , position ) ) ;
189265 return right ;
190266 }
191-
267+
192268 /* Error */
193-
269+
194270 error ( error ) {
195271 this . log ( new Event ( 'error' , [ error . stack ] ) ) ;
196272 }
197-
273+
198274 /* Analyzation */
199275
200276 analyze ( ) {
@@ -223,8 +299,8 @@ class Trace {
223299 break ;
224300 case 'error' :
225301 section = stack . pop ( ) ;
226- section . addEntry ( entry ) ;
227- stack . last . addEntry ( section )
302+ section . addEntry ( Object . assign ( new Event ( ) , entry ) ) ;
303+ this . sections . push ( section ) ;
228304 break ;
229305 default :
230306 if ( stack [ stack . length - 1 ] ) {
@@ -233,16 +309,16 @@ class Trace {
233309 event . visit ( {
234310 visitEvent ( event ) {
235311 stack . last . addEntry ( event ) ;
236- } ,
312+ } ,
237313 visitASTChangeEvent ( changeEvent ) {
238314 stack . last . addChange ( changeEvent ) ;
239315 }
240316 } ) ;
241-
317+
242318 }
243319 }
244320 }
245-
321+
246322 this . sections . push ( ...stack ) ;
247323 this . sections = this . sections . filter ( section => section . somethingHappened ( ) ) ;
248324 }
@@ -262,7 +338,7 @@ Trace.on = async function(source, pluginsUrls) {
262338 trace : Object . assign ( new Trace ( ) , JSON . parse ( data . trace ) ) ,
263339 transformedCode : data . transformedCode
264340 } ;
265-
341+
266342 const trace = obj . trace ;
267343
268344 for ( const entry of trace . _log ) {
@@ -274,7 +350,7 @@ Trace.on = async function(source, pluginsUrls) {
274350 trace . transformedAST = obj . transformedAST ;
275351
276352 trace . analyze ( ) ;
277- return trace ;
353+ return trace ;
278354}
279355
280356export default Trace ;
0 commit comments