@@ -190,8 +190,8 @@ private class Elt<Attr:{}> extends Factory<Attr, Node, Element> {
190190 ELEMENTS .update (target , nu , old );
191191
192192 static final ELEMENTS = new Updater <Element , {}>(
193- // (target, field) -> '$target.removeAttribute("$field")',
194- (target , field ) -> ' $target . $field = null ' ,
193+ (target , field ) -> ' $target .removeAttribute(" $field ")' ,
194+ (target , field , value ) -> ' $target . $field = $ value ' ,
195195 {
196196 className : function (t : Element , _ , v : String , _ ) if (! (cast v )) t .removeAttribute (' class' ) else t .className = v ,
197197 style : function (t : Element , _ , nu , old ) updateStyle (t .style , nu , old ),
@@ -227,11 +227,12 @@ private class Elt<Attr:{}> extends Factory<Attr, Node, Element> {
227227 }
228228 }
229229
230- static final STYLES = new Updater <CSSStyleDeclaration , tink.domspec. Style >(
231- (target , field ) -> ' $target . $field = null' ,
232- null ,
233- (_ , _ ) -> null
234- );
230+ static final STYLES = new Updater <CSSStyleDeclaration , tink.domspec. Style >(
231+ (target , field ) -> if (field .contains (' -' )) ' $target .removeProperty(" $field ")' else ' $target . $field = null' ,
232+ (target , field , value ) -> if (field .contains (' -' )) ' target.setProperty(" $field ", $value )' else ' $target . $field = $value ' ,
233+ null ,
234+ (_ , _ ) -> null
235+ );
235236
236237 static function updateStyle (target : CSSStyleDeclaration , newVal : tink.domspec. Style , ? oldVal : tink.domspec. Style )
237238 STYLES .update (target , newVal , oldVal );
@@ -242,117 +243,127 @@ private class Elt<Attr:{}> extends Factory<Attr, Node, Element> {
242243private typedef Rules < Target > = haxe. DynamicAccess < (target : Target , field : String , nu : Dynamic , old : Null <Dynamic >)-> Void >;
243244
244245private class Updater <Target : {}, Value : {}> {// TODO: extract to coconut.diffing
245- final unset : (target : String , field : String )-> String ;
246- final rules : Rules <Target >;
247- final getRule : (rules : Rules <Target >, field : String )-> Null <String >;
248- public function new (unset , rules , getRule ) {
249- this .unset = unset ;
250- this .rules = rules ;
251- this .getRule = getRule ;
252- }
253-
254- public function update (target : Target , newVal : Value , ? oldVal : Value ) {
255- if (newVal != null )
256- getApplicator (newVal )(target , newVal , oldVal );
257-
258- if (oldVal != null )
259- getDeleter (oldVal , newVal )(target );
260- }
261-
262- final applicators = new js.lib. Map <String , (target : Target , nu : Value , ? old : Value )-> Void >();
263- function getApplicator (obj : {}) {
264- var props = getFields (obj );
265- var key = props .toString ();
266- var apply = applicators .get (key );
267-
268- if (apply == null ) {
269- var source = ' if (old) {' ;
270-
271- function add (prefix ) {
272- for (p in props )
273- source + = ' \n ${prefix (p )}' + switch getRule (rules , p ) {
274- case null : ' if (nu. $p == null) { ${unset (' target' , p )} } else target. $p = nu. $p ;' ;
275- case rule : ' this. $rule (target, " $p ", nu. $p , old && old. $p );' ;
276- }
277- }
278-
279- add (p -> ' if (nu. $p !== old. $p ) ' );
280-
281- source + = ' \n } else {' ;
282-
283- add (p -> ' ' );
284-
285- source + = ' \n }' ;
286- apply = cast new js.lib. Function (' target' , ' nu' , ' old' , source ).bind (rules );
287- applicators .set (key , apply );
288- }
289-
290- return apply ;
291- }
292-
293- function noop (target : Target ) {}
294- final deleters = new js.lib. Map <String , (target : Target )-> Void >();
295- function getDeleter (old : {}, ? nu : {}) {
296-
297- function forFields (fields : haxe.ds. ReadOnlyArray <String >) {
298- var key = fields .toString ();
299- var ret = deleters .get (key );
300- if (ret == null ) {
301- var body = ' ' ;
302- for (f in fields )
303- body + = ' \n ' + switch getRule (rules , f ) {
246+ final unset : (target : String , field : String )-> String ;
247+ final set : (target : String , field : String , value : String )-> String ;
248+ final rules : Rules <Target >;
249+ final getRule : (rules : Rules <Target >, field : String )-> Null <String >;
250+ public function new (unset , set , rules , getRule ) {
251+ this .unset = unset ;
252+ this .set = set ;
253+ this .rules = rules ;
254+ this .getRule = getRule ;
255+ }
256+
257+ static public function get (target , property : String )
258+ return switch property .indexOf (' -' ) {
259+ case -1 : ' $target . $property ' ;
260+ default : ' $target [" $property "]' ;
261+ }
262+
263+ public function update (target : Target , newVal : Value , ? oldVal : Value ) {
264+ if (newVal != null )
265+ getApplicator (newVal )(target , newVal , oldVal );
266+
267+ if (oldVal != null )
268+ getDeleter (oldVal , newVal )(target );
269+ }
270+
271+ final applicators = new js.lib. Map <String , (target : Target , nu : Value , ? old : Value )-> Void >();
272+ function getApplicator (obj : {}) {
273+ var props = getFields (obj );
274+ var key = props .toString ();
275+ var apply = applicators .get (key );
276+
277+ if (apply == null ) {
278+ var source = ' if (old) {' ;
279+
280+ function add (prefix ) {
281+ for (p in props )
282+ source + = ' \n ${prefix (p )}' + switch getRule (rules , p ) {
283+ case null :
284+ var nu = get (' nu' , p );
285+ ' if ( $nu == null) { ${unset (' target' , p )} } else ${set (' target' , p , nu )}' ;
286+ case rule : ' this. $rule (target, " $p ", ${get (' nu' , p )}, old && ${get (' old' , p )});' ;
287+ }
288+ }
289+
290+ add (p -> ' if ( ${get (' nu' , p )} !== ${get (' old' , p )}) ' );
291+
292+ source + = ' \n } else {' ;
293+
294+ add (p -> ' ' );
295+
296+ source + = ' \n }' ;
297+ apply = cast new js.lib. Function (' target' , ' nu' , ' old' , source ).bind (rules );
298+ applicators .set (key , apply );
299+ }
300+
301+ return apply ;
302+ }
303+
304+ function noop (target : Target ) {}
305+ final deleters = new js.lib. Map <String , (target : Target )-> Void >();
306+ function getDeleter (old : {}, ? nu : {}) {
307+
308+ function forFields (fields : haxe.ds. ReadOnlyArray <String >) {
309+ var key = fields .toString ();
310+ var ret = deleters .get (key );
311+ if (ret == null ) {
312+ var body = ' ' ;
313+ for (f in fields )
314+ body + = ' \n ' + switch getRule (rules , f ) {
304315 case null : unset (' target' , f );
305316 case rule : ' this. $rule (target, " $f ", null);' ;
306317 }
307318 deleters .set (key , ret = cast new js.lib. Function (' target' , body ).bind (rules ));
308- }
309- return ret ;
310- }
311-
312- return
313- if (nu == null )
314- forFields (getFields (old ));
315- else {
316- var oldFields = getFields (old ),
317- nuFields = getFields (nu );
318-
319- var nuKey = nuFields .toString (),
320- oldKey = oldFields .toString ();
321-
322- if (nuKey == oldKey ) noop ;
323- else {
324- var key = ' ${nuKey }: ${oldKey }' ;
325- var ret = deleters .get (key );
326-
327- if (ret == null )
328- deleters .set (key , ret = forFields ([for (f in oldFields ) if (! nuFields .contains (f )) f ]));
329-
330- ret ;
331- }
332- }
333- }
334-
335- static function getFields (o : {}) {
336- var ret = js.lib. Object .getOwnPropertyNames (o );
337- switch ret {
338- case [], [_ ]:
339- case [a , b ]:
340- if (a > b ) {
341- ret [0 ] = b ;
342- ret [1 ] = a ;
343- }
344- default :
345- (cast ret ).sort ();
346- }
347- return ret ;
348- // TODO: check the caching attempt below again. Thus far profiling suggested this causes a slow down.
349- // var ret:haxe.ds.ReadOnlyArray<String> = untyped o._coco_keys;
350- // if (ret == null) {
351- // ret = untyped Object.getOwnPropertyNames(o).sort();
352- // js.lib.Object.defineProperty(o, '_coco_keys', { value: ret, enumerable: false });
353- // var joined = ret.toString();
354- // untyped ret.toString = function () return joined;
355- // }
356- // return ret;
357- }
319+ }
320+ return ret ;
321+ }
322+
323+ return
324+ if (nu == null )
325+ forFields (getFields (old ));
326+ else {
327+ var oldFields = getFields (old ),
328+ nuFields = getFields (nu );
329+
330+ var nuKey = nuFields .toString (),
331+ oldKey = oldFields .toString ();
332+
333+ if (nuKey == oldKey ) noop ;
334+ else {
335+ var key = ' ${nuKey }: ${oldKey }' ;
336+ var ret = deleters .get (key );
337+
338+ if (ret == null )
339+ deleters .set (key , ret = forFields ([for (f in oldFields ) if (! nuFields .contains (f )) f ]));
340+
341+ ret ;
342+ }
343+ }
344+ }
345+
346+ static function getFields (o : {}) {
347+ var ret = js.lib. Object .getOwnPropertyNames (o );
348+ switch ret {
349+ case [], [_ ]:
350+ case [a , b ]:
351+ if (a > b ) {
352+ ret [0 ] = b ;
353+ ret [1 ] = a ;
354+ }
355+ default :
356+ (cast ret ).sort ();
357+ }
358+ return ret ;
359+ // TODO: check the caching attempt below again. Thus far profiling suggested this causes a slow down.
360+ // var ret:haxe.ds.ReadOnlyArray<String> = untyped o._coco_keys;
361+ // if (ret == null) {
362+ // ret = untyped Object.getOwnPropertyNames(o).sort();
363+ // js.lib.Object.defineProperty(o, '_coco_keys', { value: ret, enumerable: false });
364+ // var joined = ret.toString();
365+ // untyped ret.toString = function () return joined;
366+ // }
367+ // return ret;
368+ }
358369}
0 commit comments