JAL-4046 JAL-3993 patch for 2.11.2.4 release
[jalview.git] / swingjs / differences.txt
1 java2script/SwingJS Notes
2 =========================
3
4 updated 12/31/2020 -- full support for 64-bit long
5 updated 12/6/2020 -- note about restrictions on long, including BitSet and Scanner
6 updated 3/21/2020 -- adds note about HashMap, Hashtable, and HashSet iterator ordering
7 updated 3/20/2020 -- adds note about interning, new String("xxx"), and "xxx"
8 updated 2/26/2020 -- adds Graphics.setClip issue
9 updated 12/22/19 -- additional issues
10 updated 11/03/19 -- adds information about File.exists() and points to src/javajs/async
11 updated 10/26/19 -- adds information about File.createTempFile()
12 updated 8/16/19 -- minor typos and added summary paragraph
13 updated 7/19/19 -- clarification that AWT and Swing classes are supported directly
14 updated 5/13/19 -- Mandarin U+79D8 reserved character; Missing Math methods; int and long
15 updated 5/10/19 -- adds a section on static issues in multi-(duplicate)-applet pages
16 updated 1/4/19 -- nio
17 updated 9/15/18 -- adds integer 1/0 == Infinity
18 updated 7/24/18 -- most classes replaced with https://github.com/frohoff/jdk8u-jdk
19 updated 6/5/17 -- reserved package name "window"
20 updated 3/11/17 -- myClass.getField
21 updated 3/7/17 -- overloading of JSplitPane.setDividerLocation
22 updated 3/2/17 -- more indication of classes not implemented (KeyListener)
23
24 ---IMPORTANT CHARACTER SET NOTE---
25
26 It is critical that all development work in Java2Script be done in UTF-8. This means:
27
28 - making sure your Eclipse project is set up for UTF-8 (not the Eclipse default?)
29 - making sure your server can serve up UTF-8 by default for any browser-loaded files
30 - making sure you don't edit a Java2Script class file or one of the site .js files
31     using a non-UTF-8 editor. It may replace non-Latin characters with "?" or garbage.
32 - making sure that your web pages are delivered with proper headings indicating HTML5 and UTF-8
33
34 <!DOCTYPE html>
35 <html>
36 <head>
37 <meta charset="utf-8">
38
39 Note that the DOCTYPE tag is critical for some browsers to switch into HTML5 mode. (MSIE?)
40
41
42 In particular, the Mandarin character ç§˜ (mi; "secret") is used extensively throughout
43 the SwingJS class files to distinguish j2s-specific fields and methods that must not 
44 ever be shadowed or overridden by subclasses. For example, we see in java.lang.Thread.java:
45
46                 public static JSThread ç§˜thisThread;
47
48 ----------------------------------
49
50
51
52 =============================================================================
53 SwingJS and OpenJDK 8+
54 =============================================================================
55
56 SwingJS implements a wide range of the Java language in JavaScript. The base
57 version for this implementation is OpenJDK8. some classes are implemented using 
58 older source code, and there are some missing methods. For the most part, this is 
59 no real problem. You can add or modify any java class just be adding it as source
60 in your project. Or (preferably) you can contact me, and I can get it into the 
61 distribution. Or (even more preferably) you can do that via a patch submission. 
62
63 =================
64 DESIGN PHILOSOPHY
65 =================
66
67 The java2script/SwingJS design goal is to recreate a recognizable, easily debuggable
68 equivalent in JavaScript for as much of Java as practical. This means, for example, 
69 that one can call in JavaScript 
70
71   new java.util.Hashtable()
72   
73 and for all practical purposes it will appear that Java is running.
74
75 The goal of java2script/SwingJS is NOT to reproduce Java byte code processing in a 
76 browser. We leave that task and its own issues to others. Here, instead, we have a 
77 working JavaScript version of the Java classes along with runtime assistance in the
78 j2sClazz.js library. This design has several advantages:
79
80  1) It leads to much smaller downloads, since the class loader can dynamically load
81     code at the class level. 
82     
83  2) It allow the browser to use its own optimizations and features, not to ignore those. 
84     This leads to huge performance gains and in many cases much simpler coding.
85  
86  3) It allows for in-browser debugging and analysis. 
87  
88  4) It allows for code switching between Java and JavaScript. Working Java code 
89     can be annotated (@j2sNative, @j2sAlias, @j2sIgnore) in a fashion that 
90     allows the code to run slightly differently in a Java than a JavaScript environment.
91     For example:
92     
93        int delayMS = /** @j2sNative 10 ||*/2;
94     
95     will read "var delayMS = 10 || 2;"  (i.e. 10) in JavaScript but read by the Java
96     compiler as "int delayMS = 2". 
97     
98  5) Just generally, it allows for a much more integrated environment. JavaScript on
99     the page can call into any SwingJS program, and, likewise, any SwingJS code can 
100     access anything on the page.    
101
102
103 Method and Field Disambiguation
104 -------------------------------
105
106 This is no problem. SwingJS has no problem with the overloading of methods, for example:
107
108   public void print(int b);
109   public void print(float b);
110
111 JavaScript does not allow overloading of methods, and the common practice in
112 Java of naming a field the same as a method -- isAllowed and isAllowed() -- is
113 not possible in JavaScript. As a result, SwingJS implements "fully-qualified" 
114 method names using "$" parameter type separation. Thus, these methods in SwingJS
115 will be referred to as print$I and print$F. The rules for this encoding are
116 relatively simple: 
117
118 1. The seven primitive types in Java are encoded $I (int), $L (long), $F (float), 
119 $D (double), $B (byte) $Z (boolean), and $H (short). 
120
121 2. String and Object are encoded as $S and $O, respectively.
122
123 3. "java_lang_" is dropped for all other classes in the java.lang package (as in Java).
124    For example:  $StringBuffer, not $java_lang_StringBuffer
125
126 4. All other classes are encoded as 
127
128  "$" + Class.getName().replace(".","_")
129
130 For example, in Java we see:
131
132   public void equals(Object o) {...}
133
134 Whereas in SwingJS we have:
135
136   Clazz.newMeth(C$, 'equals$O', function (o) {...}
137
138 And 
139
140  this.getContentPane().add(bar, "North");
141
142 becomes
143
144  this.getContentPane$().add$java_awt_Component$O(bar, "North");
145
146 5. Arrays are indicated with appended "A" for each level. So
147
148   setDataVector(Object[][] dataVector, Object[] columnIdentifiers)
149   
150 becomes
151
152   setDataVector$OAA$OA(dataVector, columnIdentifiers)
153
154 (It is recognized that this design does introduce a bit of ambiguity, in that
155  in principal there could be user class named XA and X in the same package,
156  and methods a(X[]) and a(XA) in the same class that cannot be distinguished.
157  The benefit of this simple system, however, triumphed over the unlikelyhood
158  of that scenario.) The transpiler could be set to flag this possibility.
159
160 6. Constructors are prepended with "c$". So 
161
162   public JLabel(String text) {...}
163   
164 becomes:
165
166   Clazz.newMeth(C$, 'c$$S', function (text) {...});
167
168 Field disambiguation involves prepending. 
169
170 In Java, a class and its subclass can both have the same field name, such as 
171
172  boolean visible;
173  
174 When this happens, it is called "shadowing", and though not recommended, Java allows
175 it. The Java2Script transpiler will prepend such shadowing fields with "$" so that the
176 subclass instance has both "visible" (for use in its methods inherited from its
177 superclass) and "$visible" (for its own methods). Thus, we might see in Java:
178
179   this.visible = super.visible;
180   
181 while in SwingJS we will see:
182
183   this.$visible=this.visible;
184
185 since JavaScript does not have the "super" keyword.
186
187 Parameterless methods such as toString() are appended with "$" to become toString$().
188 The one exception to this rule is private methods, which are saved in (truly) private 
189 array in the class (and are not accessible by reflection). Private parameterless 
190 methods retain their simple Java name, since they cannot conflict with field names.
191
192 This renaming of methods has a few consequences, which are discussed more fully below.
193 See particularly the section on "qualified field and method names", where it is described
194 how you can use packages or classes or interfaces with ".api.js" in them to represent JavaScript
195 objects for which all method names are to be left unqualified, and how individual methods
196 can have more than one name using @j2sAlias. 
197
198 The swingjs.api.js package in particular contains a number of useful interfaces that
199 you can import into your project for JavaScript-specific capabilities.
200
201
202 Applet vs. Application
203 ----------------------
204
205 One of the very cool aspects of SwingJS is that it doesn't particularly matter if a browser-based
206 Java app is an "applet" or an "application". We don't need JNLP (Java Network Launch Protocol) 
207 because now we can just start up any Java application in a browser just as easily as any applet.
208 The associative array that passes information to the SwingJS applet (information that formerly
209 might have been part of the APPLET tag, such as width, height, and codebase, always referred to 
210 in our writing as "the Info array") allows the option to specify the JApplet/Applet "code" 
211 class or the application "main" class. Either one will run just fine.
212
213
214 Performance
215 -----------
216
217 Obviously, there are limitations. One is performance, but we have seen reproducible 
218 performance at 1/6 - 1/3 the speed of Java. Achieving this performance may require
219 some refactoring of the Java to make it more efficient in both Java and JavaScript. 
220 "for" loops need to be more carefully crafted; use of "new" and "instanceof" need to be
221 minimized in critical areas. Note that method overloading -- that is, the same method name
222 with different parameters, such as read(int) and read(byte) -- is no longer any problem.   
223
224 Threads
225 -------
226
227 Although there is only a single thread in JavaScript, meaning Thread.wait(), Thread.sleep(int) and 
228 Thread.notify() cannot be reproduced, we have found that this is not a serious limitation. 
229 For example, javax.swing.Timer() works perfectly in JavaScript. All it means is that threads 
230 that use sleep(int) or notify() must be refactored to allow Timer-like callbacks. That is, 
231 they must allow full exit and re-entry of Thread.run(), not the typical while/sleep motif. 
232
233 The key is to create a state-based run() that can be exited and re-entered in JavaScript.
234
235 The javajs.async package can be added to any Java program to provide Java+JavaScript asynchronous
236 classes, including AsyncColorChooser, AsyncDialog, AsyncFileChooser, and AsyncSwingWorker. All
237 of these classes work just as well in Java as in JavaScript. There is no need to run them 
238 only when in JavaScript.
239
240 Static fields
241 -------------
242
243 Final static primitive "constant" fields (String, boolean, int, etc.) such as 
244
245 static final int TEST = 3;
246 static final String MY_STRING = "my " + "string";
247
248 are converted to their primitive form automatically by the Eclipse Java compiler 
249 and do not appear in the JavaScript by their names. 
250
251 Other static fields are properties of their class and can be used as expected.
252
253 Note, however, that SwingJS runs all "Java" code on a page in a common "jvm" 
254 (like older versions of Java). So, like the older Java schema, the JavaScript 
255 equivalents of both applets and applications will share all of their static 
256 fields and methods. This includes java.lang.System. 
257
258 Basically, SwingJS implementations of Java run in a browser page-based sandbox 
259 instead of an applet-specific one.
260
261 In general, this is no problem. But if we are to implement pages with 
262 multiple applets present, we must be sure to only have static references 
263 that are "final" or specifically meant to be shared in a JavaScript 
264 environment only (since they will not be shared in Java).
265
266 A simple solution, if static non-constant references are needed, is to attach the 
267 field to Thread.currentThread.threadGroup(), which is an applet-specific reference.
268 Be sure, if you do this, that you use explicit setters and getters:
269
270 For example, 
271
272 private static String myvar;
273
274 ...
275
276 public void setMyVar(String x) {
277   ThreadGroup g = Thread.currentThread().threadGroup();
278   /**
279    * @j2sNative g._myvar = x;
280    * 
281    */
282    {
283      myvar = x;
284    }
285 }
286
287 public String getMyVar() {
288   ThreadGroup g = Thread.currentThread().threadGroup();
289   /**
290    * @j2sNative return g._myvar || null;
291    * 
292    */
293    {
294      return myvar;
295    }
296 }
297  
298  in Java will get and set x the same in JavaScript and in Java. 
299  
300  
301 A convenient way to do this in general is to supply a singleton class with
302 explicitly private-only constructors and then refer to it in Java and in JavaScript
303 instead of using static field, referring to myclass.getIntance().xxx instead of 
304 myclass.xxx in Java (and JavaScript). 
305
306 This was done extensively in the Jalview project. See jalview.bin.Instance.
307
308
309 Helper Packages -- swingjs/ and javajs/
310 ---------------------------------------
311
312 The SwingJS library is the swingjs/ package. There are interfaces that may be of assistance
313 in swingjs/api, but other than that, it is not recommended that developers access classes in 
314 this package. The "public" nature of their methods is really an internal necessity. Most access 
315 to this package in working Java should be via the swingjs.api.JSUtilI interface.
316
317 In addition to swingjs/, though, there are several useful classes in the javajs/ package
318 that could be very useful. This package is a stand-alone package that can be 
319 cloned in any Java project that also would be great to have in any JavaScript project
320 -- SwingJS-related or not. Functionality ranges from reading and writing various file 
321 formats, including PDF, BMP, PNG, GIF, JPG, JSON, ZIP, and CompoundDocument formats.
322
323 A variety of highly efficient three- and four-dimensional point, vector, matrix, and 
324 quaternion classes are included, as they were developed for JSmol and inherited from that
325 project. 
326
327 Of particular interest should be javajs/async/, which includes
328
329 javajs.async.Async
330 javajs.async.AsyncColorChooser
331 javajs.async.AsyncDialog
332 javajs.async.AsyncFileChooser
333
334 See javajs.async.Async JavaDoc comments for a full description of 
335 these useful classes.
336
337
338 Modal Dialogs
339 -------------
340
341 Although true modal dialogs are not possible with only one thread, a functional equivalent -- 
342 asynchronous modal dialogs -- is relatively easy to set up. All the JOptionPane dialogs will
343 return PropertyChangeEvents to signal that they have been disposed of and containing the results. 
344 See below and classes in the javajs.async package.
345
346
347 Native calls
348 ------------
349
350 Native calls in Java are calls to operating system methods that are not in Java. JavaScript
351 has no access to these, of course, and they must all be replaced by JavaScript equivalents.
352 Fortunately, they are not common, and those that are present in Java (for example, in calculating
353 checksums in ZIP file creation) are at a low enough level that most developers do not utilize them
354 or do not even have access to them. All native calls in Java classes have been replaced by 
355 Java or JavaScript equivalents.
356
357
358 Swing GUI Peers and UIClasses
359 -----------------------------
360
361 One of the biggest adaptations introduced in SwingJS is in the area of the graphical 
362 user interface. Basically, what we have is a Java Swing "LookAndFeel" customized for HTML.
363
364 The issue here is complex but workable. In Java there are two background concepts -- the 
365 Component "peer" (one per "heavy-weight" component, such as a Frame) and the 
366 component "uiClass" (one per component, such as BasicButtonUI or BasicTextFieldUI).
367
368 Peers are native objects of the operating system. These are the virtual buttons and text areas
369 that the user is interacting with at a very base level. They are chunks of low-level code that
370 paint the screen to give the illusion that you really are pressing a button or typing text 
371 ot the screen. Their events are being passed on to Java or the browser by the operating system. 
372
373 UI classes provide a consistent "look and feel" for these native objects, rendering them onto 
374 the native window canvas and handling all user-generated events. They paint the borders, 
375 the backgrounds, the highlights, of every control you see in Java. There is one-to-one 
376 correspondence of Swing classes and UI classes. Setting the Look and Feel for a project amounts 
377 to selecting the directory from which to draw these UI classes. Java's UI class interfaces can
378 be found in the javax.swing.plaf ("platform look and feel") package. Individual look and feel
379 implementations are found in sun.plaf.basic, sun.plaf.metal, and other such specialized packages.
380
381 Early on in the development of SwingJS, we decided not to fully reproduce the painfully detailed 
382 bit-by-bit painting of controls as is done in Java. Instead, we felt it was wiser to utilize the standard
383 HTML5 UI capabilities as much as possible, using DIV, and INPUT especially, with extensive use
384 of CSS and sometimes jQuery (menus, and sliders, for example). Thus, we have created a new 
385 set of UIs -- the "HTML5 Look and Feel". These classes can be found in swingjs.plaf. Besides being
386 more adaptable, this approach allows far more versatility to SwingJS developers, allowing them
387 to modify the GUI to suit their needs if desired.
388
389 In SwingJS, since we have no access to native peers except through the browser DOM,
390 it seemed logical to merge the peer and UI idea. So instead of having one peer per heavy-weight control and
391 one UI class instance for each control type, we just have one UI class instance per control, and
392 that UI class instance is what is being referred to when a "peer" is notified. 
393
394 In some ways this is a throw back to when all of Swing's components were subclasses of
395 specific AWT components such as Button and List. These "heavy-weight components" all had their 
396 own individual native peers and thus automatically took on the look and feel provided by the OS. 
397 Later Swing versions implemented full look and feel for all peers, leaving only JDialog, JFrame,
398 and a few other classes to have native peers. But in SwingJS we have again a 1:1 map of component
399 and UI class/peer instance.
400
401 The origin of most issues (read "bugs") in relation to the GUI will probably be found in the
402 swingjs.plaf JSxxxxUI.java code.
403
404   
405 Swing-only Components -- no longer an issue
406 -------------------------------------------
407
408 Swing was introduced into Java well after the Java Abstract Window Toolkit (AWT) was well
409 established. As such, its designers chose to allow AWT controls such as Button and List to be used 
410 alongside their Swing counterparts JButton and JList. Reading the code, it is clear that this 
411 design choice posed a huge headache for Swing class developers. 
412
413 For SwingJS, we decided from the beginning NOT to allow this mixed-mode programming and 
414 instead to require that all components be Swing components. However, this is not really an
415 issue. We have reconfigured the class relationships a bit. In SwingJS, all AWT components
416 are now subclasses of javax.swing.JComponent. While this might seem error prone, so far we have 
417 found no problem with this arrangement. It's a little surprising to me that the original developers
418 of Swing did not think of this.
419
420  
421 The a2s Adapter Package
422 -----------------------
423
424 Originally, we thought that we would restrict ourselves to JApplets only. That is, only
425 Swing-based applets. But as we worked, we discovered that there are a lot of great 
426 applets out there that are pre-Swing pure-AWT java.applet.Applet applets. Our problem was 
427 that we also wanted it to be possible to quickly adapt these applets to JavaScript as well.
428  
429 The solution turned out to be simple: Write a package (a2s) that recreates the interface for 
430 non-Swing components as subclasses of Swing components. Thus, a2s.Button subclasses javax.swing.JButton
431 but also accepts all of the methods of java.awt.Button. This works amazingly well, with a few
432 special adaptations to the core javax.swing to be "AWT-aware." 
433
434 Then, to tie it all togeter, all AWT components such as java.awt.Button now subclass their respective
435 a2s components, which in turn subclass JComponents. So no changes in code are necessary. We have
436 successfully transpiled over 500 applets using this strategy. 
437
438 Working with Files
439 ==================
440
441 Simple String file names are not optimal for passing information about
442 files read by SwingJS applications. That is because just peeking at a file 
443 in SwingJS will load its entire byte[] data. 
444  
445 Optimally, all work with files should either use Path or File objects exclusively. 
446 These objects, after a file is read or checked for existence, will already 
447 contain the file byte[] data. The string name can be used alone, since SwingJS will
448 cache the files itself and not reload them -- just as the browser normally does.
449
450 SwingJS uses the following criteria to determine if File.exists() returns true:
451
452 (1) if this File object has been used directly to read data, or 
453 (2) if reading data using this File object is successful.
454
455 Note that you cannot check to see if a file exists before input or if it 
456 was actually written or if it already exists prior to writing in SwingJS.  
457
458 Thus, you should check each use of file.exists() carefully, and if necessary, provide a J2sNative 
459 block that gives an appropriate "OK" message, for example:
460
461 (/** @j2sNative 1 ? false : */ outputfile.exits())
462
463 or 
464
465 (/** @j2sNative 1 ? true : */ inputfile.exits())
466
467 Temporary files can be created in SwingJS. SwingJS will maintain a pseudo-filesystem for files 
468 created with File.createTempFile(). This is useful in that closure of writing to a temporary file 
469 does not generate a pseudo-download to the user's machine. Temporary files will be placed in the 
470 "/TEMP/" directory, as seen from the running Java program. Any file written to this directory will
471 simply be stored in memory; files written to any other directory, when closed, will appear to the 
472 user as a download, often involving a "What do you want to do with this file" dialog. 
473
474
475 See below for details relating to each of the subjects below:
476
477
478 UNIMPLEMENTED CLASSES BY DESIGN
479 ===============================
480
481 The SwingJS implementation of the following classes are present 
482 in a way that gracefully bypasses their functionality:
483
484 accessibility
485 security
486 serialization
487
488
489
490 TODO LIST FOR UNIMPLEMENTED CLASSES
491 ===================================
492
493 none as of 2020.12.31. Source code for classes and methods missing
494 from Java 8 or from Java 9+ can be inserted by any developer along 
495 with their running code source, and they should run.  
496
497
498 MINOR ISSUES--required some rewriting/refactoring by Bob and Udo  
499 ================================================================
500
501 Thread.currentThread() == dispatchThread
502
503
504 MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS  
505 =====================================================================
506
507 See below for a full discussion.
508
509 primitive type restrictions - int, long, and float
510 HashMap, Hashtable, and HashSet iterator ordering
511 interning, new String("xxx") vs "xxx"
512 Names with "$" and "_"
513 ArrayIndexOutOfBounds
514 java.awt.Color
515 native methods
516 javax.swing.JFileDialog
517 key focus
518 LookAndFeel and UI Classes
519 System.exit(0) does not stop all processes
520 list cell renderers must be JComponents
521 myClass.getField not implemented
522 "window" and other reserved JavaScript names
523 reserved field and method names
524 qualified field and method names
525 Component.getGraphics(), Graphics.dispose()
526 Graphics.setClip()
527
528 MAJOR ISSUES--for Bob and Udo within SwingJS
529 ============================================
530
531 fonts
532 OS-dependent classes
533 AWT component peers
534 some aspects of reflection
535
536 MAJOR ISSUES--to be resolved by implementers
537 ============================================
538
539 fonts
540 threads
541 modal dialogs
542 image loading
543 no format internationalization
544 Graphics2D: missing winding rules
545 text-related field implementation
546 Formatter/Regex limitations
547
548 ======================================================================== 
549
550 DISCUSS
551 =======
552
553 Table row/col sorter needs checking after removal of java.text.Collator references
554
555 ========================================================================== 
556
557 //////////////////////////////////////////////////////////////////////////////
558
559 UNIMPLEMENTED CLASSES
560 =====================
561
562 accessibility
563 -------------
564
565 All Accessibility handling has been commented out to save the download footprint.
566 This removes the need for sun.misc.SharedSecrets as well. 
567 Nothing says we could not implement accessibility. We just didn't.
568
569
570 security
571 --------
572
573 All JavaScript security is handled by the browser natively. 
574 Thus, Java security checking is no longer necessary, and 
575 java.security.AccessController has been simplified to work without
576 native security checking.
577
578 Note that private methods in a class are REALLY private. 
579
580
581 serialization
582 -------------
583
584 All serialization has been removed. It was never very useful for Swing anyway, 
585 because one needs exactly the same Java version to save and restore serialized objects.
586
587
588 keyboard accelerators and mnemonics
589 -----------------------------------
590
591 This work was completed in the spring of 2019. Note that in a browser, some 
592 key strokes, particularly CTRL-keys, are not available. Bummer.
593
594
595 MINOR ISSUES--required some rewriting/refactoring by Bob and Udo  
596 ================================================================
597
598
599 Thread.currentThread() == dispatchThread
600 ----------------------------------------
601
602 changed to JSToolkit.isDispatchThread()
603
604
605 MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS  
606 =====================================================================
607
608 primitive restrictions - int, long, and float
609 ---------------------------------------------
610
611 int
612
613 For performance reasons, int addition and multiplication do not by default overflow to 
614 negative values. Instead, they just get bigger. Java code that relies on overflow to 
615 negative values should be surrounded by ()|0 -- an OR with integer 0:
616
617
618 int bigI, bigJ;
619 ...
620
621 bigI = (bigI + bigJ)|0;
622
623 bigI = (bigI + 1)|0;   //instead of bigI++
624
625
626 Thus, in Java, the following is true:
627
628   2000000000 + 2000000000 == -294967296
629
630 But in SwingJS, that will be 4000000000. So, for example, the following
631 strategy will fail in SwingJS:
632
633                 int newLength = lineBuf.length * 2;
634                 if (newLength < 0) {
635                         newLength = Integer.MAX_VALUE;
636                 }
637
638 This is because, generally, "-1" in JavaScript is not 0xFFFFFFFF. The simple ()|0 takes
639 caes of this:
640
641                 int newLength = (lineBuf.length * 2)|0;
642                 if (newLength < 0) {
643                         newLength = Integer.MAX_VALUE;
644                 }
645
646 JavaScript does process bitwise operators & | ^ ~ properly for int values. There is no issue using
647 these operations. 
648
649 Note that int 1/0 in Java throws "java.lang.ArithmeticException: / by zero", but in JavaScript is just Infinity. 
650
651 Importantly, the JavaScript Int32Array does behave properly. From the Firefox developer console:
652
653 >> x = new Int32Array(1)
654 <- Int32Array(1) [ 0 ]
655 >> x[0] = 4000000000
656 <- 4000000000
657 >> x[0]
658 <- -294967296
659
660 Notice that, perhaps unexpectedly, the following two constructs produce 
661 different results in JavaScript:
662
663 x = new Int32Array(1);
664 b = x[0] = 4000000000;
665
666 (b will be 4000000000)
667
668 and
669
670 x = new Int32Array(1);
671 x[0] = 4000000000;
672 b = x[0];
673
674 (b will be -294967296)
675
676
677 SwingJS leverages array typing to handle all byte and short arithmetic so as
678 to ensure that any byte or short operation in JavaScript does give the same 
679 result in Java. 
680
681 long
682
683 Java's 64-bit long type is fully supported, starting with java2script 3.3.1 (2020.12.31)
684 The transpiler handles all conversions to and from long appropriately. See the discussion
685 at https://github.com/BobHanson/java2script/issues/202 for how this is done.
686
687 float
688
689 SwingJS does not distinguish between float and double. Everything is double.
690
691
692 HashMap, Hashtable, and HashSet iterator ordering
693 -------------------------------------------------
694
695 In Java, iterators for HashMap, Hashtable, and HashSet do not guarantee any particular order. 
696 From the HashMap documentation for Java 8:
697
698         This class makes no guarantees as to the order of the map; in particular, it does not 
699         guarantee that the order will remain constant over time.
700  
701 Likewise, for HashSet (because it is simply a convenience method for HashMap<Object,PRESENT>:
702
703         [HashSet] makes no guarantees as to the iteration order of the set.
704
705 JavaScript's Map object is different. It is basically a LinkedHashMap, so it guarantees iteration
706 in order of object addition.
707
708 Starting with java2script 3.2.9.v1, these classes use the JavaScript Map object rather than hash codes
709 whenever all keys are strictly of JavaScript typeof "string". If any key is introduced that is not a string, the
710 implementation falls back to using hash codes, the same as Java. 
711
712 The result is significantly faster performance (3-12 x faster) than originally, and up to 3 x faster
713 performance in JavaScript than in Java itself. That is not a misprint. Faster than Java. 
714
715 The JavaScript Map implementation is implemented UNLESS the constructor used is the one that
716 specifies both initial capacity and load factor in their constructor. Thus, 
717
718 new Hashtable()
719 new HashMap()
720 new HashMap(16)
721 new HashSet()
722
723 all use the JavaScript Map. But
724
725 new Hashtable(11, 0.75f)
726 new HashMap(16, 0.75f)
727 new HashSet(16, 0.75f)
728
729 do not. 
730
731 This design allows for opting out of the JavaScript Map use in order to retain the exact behavior of 
732 iterators in JavaScript as in Java.
733
734
735 interning, new String("xxx") vs "xxx"
736 -------------------------------------
737
738 Note that the following are true in JavaScript:
739
740 typeof new String("xxxx") == "object"
741 typeof "xxxx" == "string"
742 var s = "x";typeof ("xxx" + s) == "string"
743
744 There is no equivalence to this behavior in Java, where a String is a String is a String.
745
746 Be aware that SwingJS does not always create a JavaScript String object using JavaScript's 
747 new String(...) constructor. It only does this for Java new String("xxxx") or new String(new String()). 
748
749 In all other cases, new String(...) (in Java) results in a simple "xxxx" string in JavaScript. 
750 That is, it will be JavaScript typeof "string", not typeof "object". 
751
752 The reason for this design is that several classes in the Java core use toString() 
753 methods that return new String(), and those classes that do that would cause a JavaScript error
754 if implicitly stringified if new String() returned a JavaScript String object. 
755
756 This is fine in JavaScript:
757
758 test1 = function() { return { toString:function(){ return "OK" } } }
759 "testing" + new test1()
760 >> "testingOK"
761
762 But for whatever reason in JavaScript:
763
764 test2 = function() { return { toString:function(){ return new String("OK") } } }
765 "testing" + new test2()
766 >> Uncaught TypeError: Cannot convert object to primitive value
767
768 The lesson here is never to use 
769
770   return new String("...");
771
772 in a Java toString() method. In Java it will be fine; in JavaScript it will also be fine as long as
773 that method is never called in JavaScript implicitly in the context of string concatenation.
774
775 A note about interning. Consider the following six Java constructions, where we have a == "x";
776
777 "xxx"
778 "xx" + "x"
779 new String("xxx").intern()
780
781 new String("xxx")
782 "xx" + a.toString()
783 "xx" + a
784
785 All six of these will return java.lang.String for .getClass().getName().
786 However, the first three are String literals, while the last three are String objects. 
787 Thus:
788         "xxx" == "xxx"
789         "xxx" == "xx" + "x"
790         "xxx" == new String("xxx").intern()
791
792 but none of the other three are equivalent to "xxx" or each other:
793
794               "xxx" != new String("xxx")
795               "xxx" != "xx" + a.toString()
796               "xxx" != "xx" + a
797   new String("xxx") != new String("xxx") 
798            "xx" + a != new String("xxx") 
799
800 etc.
801
802 As in Java, in SwingJS, all of the following Java assertions pass as true:
803
804                 assert("xxx" == "xx" + "x"); 
805                 assert("xxx" == ("xx" + a).intern()); 
806                 assert("xxx" === new String("xxx").intern()); 
807                 
808 and both of these do as well:
809
810                 assert(new String("xxx") != "xxx"); 
811                 assert(new String("xxx") != new String("xxx")); 
812
813 But the following two fail to assert true in SwingJS:
814
815         assert("xxx" != "xx" + a);
816         assert("xxx" != "xx" + a.toString());
817
818 because, in JavaScript, both of these right-side expressions evaluate to a simple "interned" string.
819
820 In Java, however, these assertions are true because Java implicitly "boxes" String 
821 concatentaion as a String object, not a literal. 
822
823 Most of us know not to generally use == with Strings unless they are explicitly interned. 
824 Where this problem may arise, though, is in IdentityHashMap, which compares objects using 
825 System.identityHashCode(), which is not the same for different objects or their string literal equivalents.
826
827 My recommendation, if you need to use IdentityHashMap with strings is to always use an explicit String.intern()
828 for any keys -- unless you really want to keep every string as separate keys even if they are the same sequence, 
829 in which case, use new String(). This will work in Java and in JavaScript.
830
831 Be aware when working with strings that come from SwingJS and are being used by other JavaScript modules
832 that those that are String objects will return "object" for the JavaScript typeof operator, not "string".
833
834 The easy way to ensure this is no problem is to concatenate strings with "" to force immediate interning:
835
836   var x = aJavaObject.getString() + "";
837
838 unless you are certain that the string is being returned is a raw JavaScript string.   
839
840
841 Names with "$" and "_"
842 ----------------------
843
844 For the most part, this should be no problem. 
845
846 Note that the use of $ and _ in Java field names has always been discouraged:
847 [https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html]
848
849         You may find some situations where auto-generated names will contain the dollar sign, 
850         but your variable names should always avoid using it. A similar convention 
851         exists for the underscore character; while it's technically legal to begin your 
852         variable's name with "_", this practice is discouraged.
853
854 Some impacts of transpiling method names with full qualification:
855
856 1) SwingJS will introduce fields that start with $ or _. These will not conflict
857    if the above convention is followed.
858    
859 2) Fields that have the same Java name as a method are not an issue. 
860
861 3) Fields that have a Java name with $ that matches a transpiled method name, 
862    such as toString$, will need to be refactored in Java to not have that name collision.
863    
864 4) Fields in a subclass that have the same name as private fields in a superclass
865    represent a name collision, because the superclass method needs to call its private
866    field even if invoked from a subclass. The solution was to modify the subclass field
867    name using one or more prepended $.
868    
869 5) Use of Class.getDeclaredMethods() reflection will return Method objects having the transpiled 
870    name, not the Java name. This could require some j2sNative adjustment 
871    to strip the $... parameters from the name if that is needed. 
872
873 6) Use of Method.getParameterTypes() should work fine, provided class names
874    do not contain "_". This is because the transpiler converts "." to "_" when
875    creating the fully qualified JavaScript name.
876
877
878 ArrayIndexOutOfBounds
879 ---------------------
880
881 You cannot implicitly throw an ArrayIndexOutOfBoundsException in JavaScript.
882 JavaScript will simply return "undefined", not throw an Exception. So:
883
884 boolean notAGoodIdeaIsOutOfBounds(String[] sa, int i) {
885   try {
886      return (sa[i] == sa[i]);
887   } catch (ArrayIndexOutOfBoundsException e) {
888         return false;
889   }
890 }
891
892 will work in Java but not in JavaScript. Code should not depend upon this sort 
893 of trap anyway, if you ask me. 
894
895
896 Throwable vs Error vs Exception
897 -------------------------------
898
899 True JavaScript errors are trapped as Throwable, whereas you can still trap
900 Error and Exception as well. So if you want to be sure to catch any JavaScript
901 error, use try{}catch (Throwable t){}, not try{}catch (Exception e){}. 
902
903 java.awt.Color
904 --------------
905
906 ColorSpace: only "support" CS_sRGB.
907
908  TODO -- any volunteers??
909  
910
911 javax.swing.JFileDialog
912 -----------------------
913
914 HTML5 cannot expose a file reading directory structure. But you certainly 
915 can still do file reading and writing. It just works a little differently.
916 It's a simple modification:
917
918                 b = new JButton("FileOpenDialog");
919                 b.addActionListener(new ActionListener() {
920
921                         @Override
922                         public void actionPerformed(ActionEvent e) {
923                                 JFileChooser fc = new JFileChooser();
924                                 Test_Dialog.this.onDialogReturn(fc.showOpenDialog(Test_Dialog.this));
925                                 // Java will wait until the dialog is closed, then enter the onDialogReturn method.
926                                 // JavaScript will exit with NaN immediately, and then call back with its actual value
927                                 // asynchronously.
928                         }
929
930                 });
931         
932                 public void onDialogReturn(int value) {
933                         if (value != Math.floor(value))
934                                 return; // in JavaScript, this will be NaN, indicating the dialog has been opened
935                         // If we are here, the dialog has closed, in both Java and JavaScript.
936                         System.out.println("int value is " + value);
937                 }
938
939
940         @Override
941         public void propertyChange(PropertyChangeEvent event) {
942                 Object val = event.getNewValue();
943                 String name = event.getPropertyName();
944                 System.out.println(name);
945                 switch (event.getSource().getClass().getName()) {
946                 case "javax.swing.JOptionPane":
947                         switch (name) {
948                         case "inputValue":
949                                 onDialogReturn(val);
950                                 return;
951                         case "value":
952                                 if (val instanceof Integer)
953                                         onDialogReturn(((Integer) val).intValue());
954                                 else
955                                         onDialogReturn(val);
956                                 return;
957                         }
958                         break;
959                 case "javax.swing.ColorChooserDialog":
960                         switch (name) {
961                         case "SelectedColor":
962                                 onDialogReturn(val);
963                                 return;
964                         }
965                         break;
966                 case "javax.swing.JFileChooser":
967                         switch (name) {
968                         case "SelectedFile":
969                                 File file = (File) val;
970                                 byte[] array = (val == null ? null : /** @j2sNative file.秘bytes || */
971                                                 null);
972                                 onDialogReturn("fileName is '" + file.getName() + "'\n\n" + new String(array));
973                                 return;
974                         }
975                         break;
976                 }
977                 System.out.println(
978                                 event.getSource().getClass().getName() + " " + event.getPropertyName() + ": " + event.getNewValue());
979         }
980
981
982 Developers are encouraged to create a separate class that handles general calls to JFileDialog. 
983 An example class can be found in the SwingJS distribution as 
984
985 /sources/net.sf.j2s.java.core/src/javajs/async/AsyncFileChooser.java.
986
987
988 javax.swing.JOptionPane dialogs
989 -------------------------------
990
991 For a full discussion of modal dialogs, see the javajs.asyc.AsyncDialog.java discussion.
992
993 For this action to work, the parent component must implement
994 propertyChangeListener, and any call to JOptionPanel should allow for
995 an asynchronous response, meaning that there is no actionable code following the
996 call to the dialog opening. 
997
998 In addition, for compatibility with the Java version, implementation should
999 wrap the call to getConfirmDialog or getOptionDialog in a method call to
1000 handle the Java:
1001
1002 onDialogReturn(JOptionPane.showConfirmDialog(parentFrame,
1003 messageOrMessagePanel, "title", JOptionPane.OK_CANCEL_OPTION));
1004
1005 Then parentFrame.propertyChange(event) should also call onDialogReturn.
1006
1007 This will then work in both Java and JavaScript.
1008
1009 Note that there is an int and an Object version of onDialogReturn().
1010
1011
1012 In JavaScript:
1013
1014 The initial return from JOptionPane.showConfirmDialog and showMessageDialog
1015 will be (SwingJS) JDialog.ASYNCHRONOUS_INTEGER (NaN), testable as an impossible 
1016 Java int value using ret != -(-ret) if the parent implements PropertyChangeListener, or -1
1017 (CLOSE_OPTION) if not.
1018
1019 For showOptionDialog (which returns Object) or showInputDialog (which returns
1020 String), the initial return will be (SwingJS) JDialog.ASYNCHRONOUS_OBJECT, testable as
1021 ((Object) ret) instanceof javax.swing.plaf.UIResource if the parent implements
1022 PropertyChangeListeneer, or null if not.
1023
1024 The second return will be the desired return.
1025
1026 In Java:
1027
1028 The initial return will be the one and only modal final return.
1029
1030
1031
1032 For full compatibility, The calling method must not continue beyond this call.
1033
1034 All of the standard Java events associated with Components are also available.
1035
1036 Certain fall back mechanisms are possible, where onReturn does not exist, but
1037 only for the following cases:
1038
1039
1040 For showMessageDialog, for WARNING_MESSAGE and ERROR_MESSAGE, a simple
1041 JavaScript alert() is used, returning 0 (OK_OPTION) or -1 (CLOSED_OPTION).
1042
1043 For showInputDialog, if the message is a string, a simple JavaScript prompt()
1044 with input box is used, returning the entered string or null.
1045
1046 For showConfirmDialog, a simple JavaScript confirm() is used, in which case:
1047
1048 for YES_NO_OPTION: YES_OPTION or NO_OPTION
1049
1050 for YES_NO_CANCEL_OPTION: YES_OPTION or CANCEL_OPTION
1051
1052 for OK_CANCEL_OPTION or any other: OK_OPTION or CANCEL_OPTION
1053
1054 Note that you should implement a response for CLOSED_OPTION for
1055 showConfirmDialog. For other dialogs, a null return indicates the dialog was
1056 closed, just as for Java.
1057
1058 Developers are encouraged to create a separate class that handles general calls. 
1059 An example class can be found in the SwingJS distribution as src/javajs/async/AsyncDialog.java.
1060 Very simple modifications to the Java allows asynchronous operation using AsyncDialog. Here
1061 is a simple "do you want to close this frame" example, where you can see that what we have
1062 done is to set the reply into an ActionListener that is defined in the constructor of 
1063 the AsyncDisplay object:
1064
1065 // Original:
1066 //
1067 //      private void promptQuit() {
1068 //              int sel = JOptionPane.showConfirmDialog(null, PROMPT_EXIT, NAME, JOptionPane.YES_NO_OPTION);
1069 //              switch (sel) {
1070 //              case JOptionPane.YES_OPTION:
1071 //                      resultsTab.clean();
1072 //                      seqs.dispose();
1073 //                      if (fromMain) {
1074 //                              System.exit(0);
1075 //                      }
1076 //                      break;
1077 //              }
1078 //      }
1079
1080         private void promptQuitAsync() {
1081                 new AsyncDialog(new ActionListener() {
1082
1083                         @Override
1084                         public void actionPerformed(ActionEvent e) {
1085                             int sel = ((AsyncDialog)e.getSource()).getOption();
1086                                 switch (sel) {
1087                                 case JOptionPane.YES_OPTION:
1088                                         resultsTab.clean();
1089                                         seqs.dispose();
1090                                         if (fromMain) {
1091                                                 System.exit(0);
1092                                         }
1093                                         break;
1094                                 }
1095                         }}).showConfirmDialog(null, PROMPT_EXIT, NAME, JOptionPane.YES_NO_OPTION);
1096         }
1097
1098 Very simple! 
1099
1100
1101 native methods
1102 --------------
1103
1104 The J2S compiler ignores all static native method declarations.
1105 Anything of this nature needs to be implemented in JavaScript if it is needed,
1106 using j2sNative blocks:
1107
1108 /**
1109  * @j2sNative
1110  *
1111  *    var putYourJavaScriptCodeHere
1112  *
1113  */
1114  
1115  Note that if you follow that directly with a {...} block, then 
1116  only the javadoc code will run in JavaScript, and only the {...} code will run in Java.
1117  
1118  
1119 key Focus
1120 ---------
1121
1122 As of June, 2019, the keyboard focus manager is fully implemented. 
1123 The one catch is that JTextPane and JTextArea, which already consume
1124 VK_TAB in Java, cannot use CTRL-TAB to continue a tabbing cycle around
1125 the components in a window. Instead, CTRL-TAB is absorbed by the browser. 
1126
1127
1128 LookAndFeel and UI Classes
1129 --------------------------
1130
1131 SwingJS implements the native browser look and feel as swingjs.plaf.HTML5LookAndFeel. 
1132 There are small differences between all look and feels -- MacOS, Windows, SwingJS.
1133
1134 Expert developers know how to coerce changes in the UI by subclassing the UI for a 
1135 component. This probably will not work in SwingJS. 
1136
1137 Note that LookAndFeel in Java usually determines canvas size in a Frame because 
1138 different operating systems (Mac OS vs Windows vs HTML5) will have 
1139 different edge sizes on their frames. If you want to ensure a component size, 
1140 use getContentPane().setPreferredSize().
1141
1142
1143 System.exit(0) does not stop all processes
1144 ------------------------------------------
1145
1146 Although System.ext(int) has been implemented in JavaScript, it just closes the 
1147 frames, stops all pending javax.swing.Timer objects in the queue, and runs any 
1148 threads added using Runtime.getRuntime().addShutdownHook(Thread).
1149 It may not stop all "threads." So don't rely on that.
1150 Applications are responsible for shutting down prior to executing System.exit(0). 
1151
1152
1153 myClass.getField not implemented
1154 --------------------------------
1155
1156 java.lang.reflect.Field is implemented minimally. It is not
1157 certain that Field.getDeclaringClass() will work. If you just want a 
1158 value of a field, you can do this:
1159
1160 /**
1161  *@j2sNative
1162  *
1163  * return myClass[name]
1164  */   
1165
1166 But that is not a java.lang.reflection.Field object.
1167
1168
1169 "window" and other reserved JavaScript names
1170 --------------------------------------------
1171
1172 No reserved top-level JavaScript name is allowed for a package name. So, for example, 
1173 one must rename packages such as "window" or "document" to names such as "win" or "doc".
1174
1175
1176 reserved field and method names
1177 -------------------------------
1178
1179 In order to minimize the chance of added SwingJS field and method names colliding with ones 
1180 developers might use in subclassing Java classes, we have added U+79D8 (first character of Mandarin 
1181 "secret") to the characters already disrecommended by Java documentation ("$" and "_"). The only problem
1182 would be if you use that character followed by certain English words in certain classes. For example
1183 \u79D8canvas for JComponents (in java.awt.JSComponent) and \u79D8byte (in java.io.File).
1184
1185
1186 qualified field and method names
1187 --------------------------------
1188
1189 Method names in SwingJS are fully qualified, meaning two methods with the same Java name but different
1190 parameters, such as write(int) and write(double), must not have the same name in JavaScript. (In this
1191 case, we will have write$I and write$D.) However, in certain cases it may be desirable to leave the
1192 method names unqualified. In particular, when an interface actually represents a JavaScript object, 
1193 the transpiler can leave a method name unqualified. 
1194
1195 You can implement a simple name for a method using the @j2sAlias annoation in the javadoc for the 
1196 method involved. For example:
1197
1198
1199 /**
1200  * @j2sAlias read
1201  *
1202  */
1203 public void read(byte[] buf, int pos, int len) {...}
1204
1205 will allow the method to be accesible either as "read" or "read$BA$I$I" in JavaScript. 
1206
1207
1208 The default situation for this is a class name includes ".api.js" (case-sensitive). 
1209 This means that any method in any class in a package js within a package api, or any private interface js 
1210 that has an outer interface api, will have all-unqualified methods. An example of this is 
1211 swingjs.plaf.JSComboPopupList, which needs to communicate with a jQuery 
1212 object directly using the following interface:
1213
1214         private interface api {
1215
1216                 interface js extends JQueryObject {
1217
1218                         abstract js j2sCB(Object options);
1219
1220                         abstract Object[] j2sCB(String method);
1221
1222                         abstract Object[] j2sCB(String method, Object o);
1223
1224                         abstract Object[] j2sCB(String method, int i);
1225
1226                         abstract int j2sCB(String OPTION, String name);
1227
1228                 }
1229         }
1230
1231 Notice that all these variants of j2sCB() will call the same method in JavaScript by design.
1232
1233
1234 Component.getGraphics(), Graphics.dispose()
1235 -------------------------------------------
1236
1237 Use of component.getGraphics() is discouraged in Java and in SwingJS. 
1238 Specifically in SwingJS, any call to component.getGraphics() or 
1239 BufferedImage.createGraphics() or Graphics.create(...) should be matched with graphics.dispose(), 
1240 particularly when it is called outside the context of a paint(Graphics) call from the system. 
1241
1242 If you see your graphics scrolling down the page with each repaint, 
1243 look for where you have used Component.getGraphics() and not Graphics.dispose().
1244 For example, this will definitely NOT work in SwingJS:
1245
1246   this.paint(getGraphics())
1247   
1248 and really should not work in Java, either, as it is technically a resource memory leak.
1249
1250 Instead, if you really do not want to use repaint(), use this:
1251
1252   Graphics g = getGraphics();
1253   paint(g);
1254   g.dispose();
1255
1256
1257
1258 Graphics.setClip()
1259 ------------------
1260
1261 The HTML5 canvas.clip() method is permanent. You can only reset the clip using
1262 save/restore. This is different from Java, where you can temporarily change it using
1263
1264   Shape oldClip = Graphics.getClip();
1265   Graphics.setClip(newClip);
1266    ...
1267   Graphics.setClip(oldClip); 
1268
1269 If you need to do something like this, you must schedule the paints to not have overlapping clip needs.
1270
1271
1272 MAJOR ISSUES--for Bob and Udo within SwingJS
1273 ============================================
1274
1275 fonts
1276 -----
1277
1278 Fonts and FontMetrics will all be handled in JavaScript. Font matching will 
1279 not be exact, and composite (drawn) fonts will not be supported. 
1280
1281 SwingJS handles calls such as font.getFontMetrics(g).stringWidth("xxx") by 
1282 creating a <div> containing that text, placing it in an obscure location on 
1283 the page, and reading div.getBoundingClientRect(). This is a VERY precise
1284 value, but can be a pixel or two off from what Java reports for the same font.
1285  
1286  
1287 OS-dependent classes
1288 --------------------
1289
1290 Static classes such as:
1291
1292    java.awt.Toolkit
1293    java.awt.GraphicsEnvironment
1294       
1295 which are created using Class.forName are implemented using classes in the swingjs package.
1296
1297 sun.awt.AWTAccessor is not implemented. 
1298
1299    
1300 AWT component peers and component "ui" user interfaces
1301 ------------------------------------------------------
1302
1303 ComponentPeer is a class that represents a native AWT component.
1304 Components with such peers are called "heavy-weight" components.
1305 They are expected to do the dirty work of graphics drawing. 
1306
1307 Java Swing implements peers only for JApplet, JDialog, JFrame, and JWindow. 
1308 References to such objects have been removed, but clearly there must be 
1309 some connection to similar DOM objects, even for "light-weight" components. 
1310
1311   
1312 MAJOR ISSUES--to be resolved by implementers
1313 ============================================
1314
1315 fonts
1316 -----
1317
1318 Glyph/composite/outline fonts are not supported.
1319    
1320
1321
1322 threads
1323 -------
1324
1325 Thread locking and synchronization are not relevant to JavaScript.
1326 Thus, anything requiring "notify.." or "waitFor.." could be a serious issue.
1327  
1328 All threading must be "faked" in JavaScript. Specifically not available is:
1329
1330   Thread.sleep()
1331   
1332 javax.swing.AbstractButton#doClick(pressTime) will not work, as it requires Thread.sleep();
1333     
1334 However, java.lang.Thread itself is implemented and used extensively. 
1335
1336 Methods thread.start() and thread.run() both work fine. 
1337
1338 For simple applications that use Thread.sleep() just to have a delay, as in a frame rate, for 
1339 example, one can use javax.swing.Timer instead. That is fully implemented. 
1340
1341 Likewise, java.util.Timer can be replaced with no loss of performance with javax.Swing.Timer.
1342 Note that java.util.TimerTask is implemented, but it can also be replaced by an implementation of Runnable.
1343
1344 task = new TimerTask(){....};
1345 t = new java.util.Timer();
1346 t.schedule(task, 0, 1);
1347
1348 becomes
1349
1350 task = new TimerTask(){....}; // or task = new Runnable() {...}
1351 t = new javax.swing.Timer(1, new ActionListener() {
1352         @Override
1353         public void actionPerformed(ActionEvent e) {
1354                 task.run();
1355         }
1356 };
1357 t.setInitialDelay(0); // not particularly necessary
1358 t.start();
1359
1360 In addition, SwingJS provides swingjs.JSThread, which can be subclassed
1361 if desired. This class allows simple 
1362
1363   while(!interrupted()){
1364         wait()
1365         ...
1366   }  
1367
1368 action through an asynchronous function run1(mode). For example:
1369
1370         protected void run1(int mode) {
1371                 try {
1372                         while (true)
1373                                 switch (mode) {
1374                                 case INIT:
1375                                         // once-through stuff here
1376                                         mode = LOOP;
1377                                         break;
1378                                 case LOOP:
1379                                         if (!doDispatch || isInterrupted()) {
1380                                                 mode = DONE;
1381                                         } else {
1382                                                 Runnable r = new Runnable() {
1383                                                         public void run() {
1384                                                                 // put the loop code here
1385                                                         }
1386                                                 };
1387                                                 dispatchAndReturn(r);
1388                                                 if (isJS)
1389                                                         return;
1390                                         }
1391                                         break;
1392                                 // add more cases as needed
1393                                 case DONE:
1394                                         // finish up here
1395                                         if (isInterrupted())
1396                                                 return;
1397                                         // or here
1398                                         break;
1399                                 }
1400                 } finally {
1401                         // stuff here to be executed after each loop in JS or at the end in Java
1402                 }
1403         }
1404
1405
1406 image loading
1407 -------------
1408 - All image loading in SwingJS is synchronous. A MediaTracker call will immediately return "complete".
1409   However, it still may take one system clock tick to fully load images. Thus, it is recommended that
1410   images be preloaded in the static block of the applet if it is necessary that they be available in init().
1411   This is only an issue if you are trying to access the pixel buffer of the image in JavaScript. 
1412   
1413 - Applet.getImage(path, name) will return null if the image does not exist. 
1414
1415 - BufferedImage: only "support" imageType RGB and ARGB
1416
1417   -BH: This is a temporary edit, just to get us started. Certainly GRAY will be needed
1418
1419
1420 BigInteger and BigDecimal
1421 -------------------------
1422
1423 java.math.BigInteger and java.math.BigDecimal are fully supported. 
1424
1425
1426 no format internationalization
1427 ------------------------------
1428
1429 For now, just "en" for number and date formatters
1430
1431
1432 missing winding rules
1433 ---------------------
1434
1435 When filling a graphic, only nonzero winding rule is implemented in HTML5 Canvas2D.
1436
1437
1438
1439 text-related field implementation
1440 ---------------------------------
1441
1442 Text fields are:
1443
1444 JTextField   (JavaScript <input type="text">)
1445 JTextArea    (JavaScript <textarea>)
1446 JTextPane    (JavaScript <div>)
1447 JEditorPane  (JavaScript <div>)
1448
1449 For the initial implementation, we don't implement infinite undo/redo, and the abstract 
1450 document model is much less elaborate. Only PlainDocument (in the form of JSPlainDocument)
1451 is implemented. The Document returned by JTextField.getDocument() is a javax.swing.text.Document.
1452
1453 All scrolling is handled by HTML5. javax.swing.AutoScroller is not implemented.
1454 public static methods .stop, .isRunning, .processMouseDragged require true Java threading
1455 and so are not implmented. javax.swing.text.View and its subclasses are not implemented. 
1456
1457 The JS document model does not allow two text fields to address the same underlying document. 
1458
1459 JavaScript is slightly different from Java in that the field value is changed asynchronously after
1460 the keypressed event, so Java actions that are keyed to KEY_PRESSED may not pick up the new 
1461 key value even after SwingUtilities.invokeLater() is called. Thus, key pressed actions may need
1462 to be recorded after a key released event instead. 
1463
1464
1465 Formatter/Regex limitations
1466 ---------------------------
1467
1468 Some browsers cannot process Regex "look-behind" process such as (?<=\W)
1469 java.util.regex.Matcher and Pattern use JavaScript's RegExp object rather than
1470 the native Java object. These are not identical. Only flags /igm are supported.
1471 Matcher.start(groupID) is not supported.
1472
1473 java.util.Formatter will function correctly for all standard %... patterns.
1474
1475 In addition, JavaScript does not implement some of the more arcane POSIX {...} formats. 
1476 From java.util.regex.Pattern.java, we find the listing of conversions SwingJS does use:
1477
1478                 "\\p{javaWhitespace}","\\s",
1479                 "\\p{javaDigit}","\\d",
1480                 "\\p{Lower}", "[a-z]",
1481                 "\\p{Upper}", "[A-Z]",
1482                 "\\p{ASCII}", "[\u0000-\u007F]",
1483                 "\\p{Alpha}", "[A-Za-z]",
1484                 "\\p{Digit}", "[0-9]",
1485                 "\\p{Alnum}", "[A-Za-z0-9]",
1486                 "\\p{Punct}", "[!\"#$%&'\\(\\)\\*\\+,-./:;<=>?@\\[\\\\\\]^_`{\\|}~]",
1487                 "\\p{Graph}", "[A-Za-z0-9]!\"#$%&'\\(\\)\\*\\+,-./:;<=>?@\\[\\\\\\]^_`{\\|}~]",
1488                 "\\p{Print}", "[A-Za-z0-9]!\"#$%&'\\(\\)\\*\\+,-./:;<=>?@\\[\\\\\\]^_`{\\|}~]",
1489                 "\\p{Blank}", "[ \t]",
1490                 "\\p{Cntrl}", "[\u0000-\u001F\u007F]",
1491                 "\\p{XDigit}", "[0-9a-fA-F]",
1492                 "\\p{Space}", "[ \t\n\u000B\f\r]",
1493                 "\\p{javaLowerCase}", "[a-z]",
1494                 "\\p{javaUpperCase}", "[A-Z]",
1495                 "\\p{Sc}", "[\u0024\u00A2\u00A3\u00A4\u00A5\u058F\u060B\u07FE\u07FF\u09F2\u09F3\u09FB\u0AF1\u0BF9\u0E3F\u20A0\u20A1\u20A2\u20A3\u20A4\u20A5\u20A6\u20A7\u20A8\u20A9\u20AA\u20AB\u20AC\u20AD\u20AE\u20AF\u20B0\u20B1\u20B2\u20B3\u20B4\u20B5\u20B6\u20B7\u20B8\u20B9\u20BA\u20BB\u20BC\u20BD\u20BE\u20BF\uA838\uFDFC\uFE69\uFF04\uFFE0\uFFE1\uFFE5\uFFE6]"
1496
1497 Java's \Q \E quoting is handled appropriately.
1498
1499 Additional Issues
1500 -----------------
1501
1502 Method reflection is limited. Fields and methods do not retain public or default characteristics. 
1503 (This could be easily adapted, though.) Interfaces do not expose their methods, as the transpiler does not 
1504 actually transpile the interfaces themselves unless they contain default methods. 
1505 And method reflection only includes annotated methods.
1506
1507 java.util.concurrent is not fully elaborated. This package is rewritten to not actually use the
1508 memory handling capabilities of concurrency, which JavaScript does not have access to.
1509
1510 System.getProperties() just returns a minimal set of properties.
1511
1512
1513 Summary
1514 -------
1515
1516 These are all the known limitations of SwingJS. We have not found any of these limitations
1517 to be show-stoppers. The primary issue for newcomers to SwingJS is having the source code.
1518 You must check that source code for all your library jar files is available or, if you
1519 choose, you will need to decompile those classes. We have used decompilation on some projects,
1520 and it works just fine. So, technically, all we really need are JAR/class files. But the 
1521 source is by far superior. It's generally prettier, and it has the license information that
1522 may or may not be present with the JAR or class files. Use class files at your own risk.
1523
1524 Bob Hanson
1525
1526