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