001package Torello.Browser.BrowserAPI;
002
003import java.util.*;
004import javax.json.*;
005import javax.json.stream.*;
006import java.io.*;
007
008import java.lang.reflect.Method;
009import java.lang.reflect.Parameter;
010import java.util.function.Function;
011
012import Torello.Browser.BrowserEvent;
013import Torello.Browser.JavaScriptAPI.*;
014import Torello.Browser.helper.*;
015
016import Torello.Java.Additional.*;
017import Torello.Java.JSON.*;
018
019import static Torello.Java.JSON.JFlag.*;
020
021import Torello.Java.StrCmpr;
022import Torello.JavaDoc.StaticFunctional;
023import Torello.JavaDoc.JDHeaderBackgroundImg;
024import Torello.JavaDoc.Excuse;
025
026/**
027 * <SPAN CLASS=COPIEDJDK><B><CODE>[No Description Provided by Google]</CODE></B></SPAN>
028 * 
029 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE>
030 */
031@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION})
032@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE")
033public class Memory
034{
035    // ********************************************************************************************
036    // ********************************************************************************************
037    // Class Header Stuff
038    // ********************************************************************************************
039    // ********************************************************************************************
040
041
042    // No Pubic Constructors
043    private Memory () { }
044
045    // These two Vector's are used by all the "Methods" exported by this class.  java.lang.reflect
046    // is used to generate the JSON String's.  It saves thousands of lines of Auto-Generated Code.
047    private static final Map<String, Vector<String>>    parameterNames = new HashMap<>();
048    private static final Map<String, Vector<Class<?>>>  parameterTypes = new HashMap<>();
049
050    // Some Methods do not take any parameters - for instance all the "enable()" and "disable()"
051    // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now,
052    // offically, two empty-vectors.  One for String's, and the other for Classes.
053
054    private static final Vector<String>     EMPTY_VEC_STR = new Vector<>();
055    private static final Vector<Class<?>>   EMPTY_VEC_CLASS = new Vector<>();
056
057    static
058    {
059        for (Method m : Memory.class.getMethods())
060        {
061            // This doesn't work!  The parameter names are all "arg0" ... "argN"
062            // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter!
063            //
064            // Vector<String> parameterNamesList = new Vector<>(); -- NOPE!
065
066            Vector<Class<?>> parameterTypesList = new Vector<>();
067        
068            for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType());
069
070            parameterTypes.put(
071                m.getName(),
072                (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS
073            );
074        }
075    }
076
077    static
078    {
079        Vector<String> v = null;
080
081        parameterNames.put("getDOMCounters", EMPTY_VEC_STR);
082
083        parameterNames.put("getDOMCountersForLeakDetection", EMPTY_VEC_STR);
084
085        parameterNames.put("prepareForLeakDetection", EMPTY_VEC_STR);
086
087        parameterNames.put("forciblyPurgeJavaScriptMemory", EMPTY_VEC_STR);
088
089        v = new Vector<String>(1);
090        parameterNames.put("setPressureNotificationsSuppressed", v);
091        Collections.addAll(v, new String[]
092        { "suppressed", });
093
094        v = new Vector<String>(1);
095        parameterNames.put("simulatePressureNotification", v);
096        Collections.addAll(v, new String[]
097        { "level", });
098
099        v = new Vector<String>(2);
100        parameterNames.put("startSampling", v);
101        Collections.addAll(v, new String[]
102        { "samplingInterval", "suppressRandomness", });
103
104        parameterNames.put("stopSampling", EMPTY_VEC_STR);
105
106        parameterNames.put("getAllTimeSamplingProfile", EMPTY_VEC_STR);
107
108        parameterNames.put("getBrowserSamplingProfile", EMPTY_VEC_STR);
109
110        parameterNames.put("getSamplingProfile", EMPTY_VEC_STR);
111    }
112
113
114    // ********************************************************************************************
115    // ********************************************************************************************
116    // Types - Static Inner Classes
117    // ********************************************************************************************
118    // ********************************************************************************************
119
120    /** Memory pressure level. */
121    public static final String[] PressureLevel =
122    { "moderate", "critical", };
123    
124    /** Heap profile sample. */
125    public static class SamplingProfileNode
126        extends BaseType
127        implements java.io.Serializable
128    {
129        /** For Object Serialization.  java.io.Serializable */
130        protected static final long serialVersionUID = 1;
131        
132        public boolean[] optionals()
133        { return new boolean[] { false, false, false, }; }
134        
135        /** Size of the sampled allocation. */
136        public final Number size;
137        
138        /** Total bytes attributed to this sample. */
139        public final Number total;
140        
141        /** Execution stack at the point of allocation. */
142        public final String[] stack;
143        
144        /**
145         * Constructor
146         *
147         * @param size Size of the sampled allocation.
148         * 
149         * @param total Total bytes attributed to this sample.
150         * 
151         * @param stack Execution stack at the point of allocation.
152         */
153        public SamplingProfileNode(Number size, Number total, String[] stack)
154        {
155            // Exception-Check(s) to ensure that if any parameters which are not declared as
156            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
157            
158            if (size == null)  THROWS.throwNPE("size");
159            if (total == null) THROWS.throwNPE("total");
160            if (stack == null) THROWS.throwNPE("stack");
161            
162            this.size   = size;
163            this.total  = total;
164            this.stack  = stack;
165        }
166        
167        /**
168         * JSON Object Constructor
169         * @param jo A Json-Object having data about an instance of {@code 'SamplingProfileNode'}.
170         */
171        public SamplingProfileNode (JsonObject jo)
172        {
173            this.size   = ReadNumberJSON.get(jo, "size", false, true);
174            this.total  = ReadNumberJSON.get(jo, "total", false, true);
175            this.stack = (jo.getJsonArray("stack") == null)
176                ? null
177                : RJArrIntoStream.strArr(jo.getJsonArray("stack"), null, 0).toArray(String[]::new);
178        
179        }
180        
181        
182        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
183        public boolean equals(Object other)
184        {
185            if (this == other)                       return true;
186            if (other == null)                       return false;
187            if (other.getClass() != this.getClass()) return false;
188        
189            SamplingProfileNode o = (SamplingProfileNode) other;
190        
191            return
192                    Objects.equals(this.size, o.size)
193                &&  Objects.equals(this.total, o.total)
194                &&  Arrays.deepEquals(this.stack, o.stack);
195        }
196        
197        /** Generates a Hash-Code for {@code 'this'} instance */
198        public int hashCode()
199        {
200            return
201                    Objects.hashCode(this.size)
202                +   Objects.hashCode(this.total)
203                +   Arrays.deepHashCode(this.stack);
204        }
205    }
206    
207    /** Array of heap profile samples. */
208    public static class SamplingProfile
209        extends BaseType
210        implements java.io.Serializable
211    {
212        /** For Object Serialization.  java.io.Serializable */
213        protected static final long serialVersionUID = 1;
214        
215        public boolean[] optionals()
216        { return new boolean[] { false, false, }; }
217        
218        /** <CODE>[No Description Provided by Google]</CODE> */
219        public final Memory.SamplingProfileNode[] samples;
220        
221        /** <CODE>[No Description Provided by Google]</CODE> */
222        public final Memory.Module[] modules;
223        
224        /**
225         * Constructor
226         *
227         * @param samples -
228         * 
229         * @param modules -
230         */
231        public SamplingProfile(Memory.SamplingProfileNode[] samples, Memory.Module[] modules)
232        {
233            // Exception-Check(s) to ensure that if any parameters which are not declared as
234            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
235            
236            if (samples == null) THROWS.throwNPE("samples");
237            if (modules == null) THROWS.throwNPE("modules");
238            
239            this.samples  = samples;
240            this.modules  = modules;
241        }
242        
243        /**
244         * JSON Object Constructor
245         * @param jo A Json-Object having data about an instance of {@code 'SamplingProfile'}.
246         */
247        public SamplingProfile (JsonObject jo)
248        {
249            this.samples = (jo.getJsonArray("samples") == null)
250                ? null
251                : RJArrIntoStream.objArr(jo.getJsonArray("samples"), null, 0, Memory.SamplingProfileNode.class).toArray(Memory.SamplingProfileNode[]::new);
252        
253            this.modules = (jo.getJsonArray("modules") == null)
254                ? null
255                : RJArrIntoStream.objArr(jo.getJsonArray("modules"), null, 0, Memory.Module.class).toArray(Memory.Module[]::new);
256        
257        }
258        
259        
260        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
261        public boolean equals(Object other)
262        {
263            if (this == other)                       return true;
264            if (other == null)                       return false;
265            if (other.getClass() != this.getClass()) return false;
266        
267            SamplingProfile o = (SamplingProfile) other;
268        
269            return
270                    Arrays.deepEquals(this.samples, o.samples)
271                &&  Arrays.deepEquals(this.modules, o.modules);
272        }
273        
274        /** Generates a Hash-Code for {@code 'this'} instance */
275        public int hashCode()
276        {
277            return
278                    Arrays.deepHashCode(this.samples)
279                +   Arrays.deepHashCode(this.modules);
280        }
281    }
282    
283    /** Executable module information */
284    public static class Module
285        extends BaseType
286        implements java.io.Serializable
287    {
288        /** For Object Serialization.  java.io.Serializable */
289        protected static final long serialVersionUID = 1;
290        
291        public boolean[] optionals()
292        { return new boolean[] { false, false, false, false, }; }
293        
294        /** Name of the module. */
295        public final String name;
296        
297        /** UUID of the module. */
298        public final String uuid;
299        
300        /**
301         * Base address where the module is loaded into memory. Encoded as a decimal
302         * or hexadecimal (0x prefixed) string.
303         */
304        public final String baseAddress;
305        
306        /** Size of the module in bytes. */
307        public final Number size;
308        
309        /**
310         * Constructor
311         *
312         * @param name Name of the module.
313         * 
314         * @param uuid UUID of the module.
315         * 
316         * @param baseAddress 
317         * Base address where the module is loaded into memory. Encoded as a decimal
318         * or hexadecimal (0x prefixed) string.
319         * 
320         * @param size Size of the module in bytes.
321         */
322        public Module(String name, String uuid, String baseAddress, Number size)
323        {
324            // Exception-Check(s) to ensure that if any parameters which are not declared as
325            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
326            
327            if (name == null)        THROWS.throwNPE("name");
328            if (uuid == null)        THROWS.throwNPE("uuid");
329            if (baseAddress == null) THROWS.throwNPE("baseAddress");
330            if (size == null)        THROWS.throwNPE("size");
331            
332            this.name         = name;
333            this.uuid         = uuid;
334            this.baseAddress  = baseAddress;
335            this.size         = size;
336        }
337        
338        /**
339         * JSON Object Constructor
340         * @param jo A Json-Object having data about an instance of {@code 'Module'}.
341         */
342        public Module (JsonObject jo)
343        {
344            this.name         = ReadJSON.getString(jo, "name", false, true);
345            this.uuid         = ReadJSON.getString(jo, "uuid", false, true);
346            this.baseAddress  = ReadJSON.getString(jo, "baseAddress", false, true);
347            this.size         = ReadNumberJSON.get(jo, "size", false, true);
348        }
349        
350        
351        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
352        public boolean equals(Object other)
353        {
354            if (this == other)                       return true;
355            if (other == null)                       return false;
356            if (other.getClass() != this.getClass()) return false;
357        
358            Module o = (Module) other;
359        
360            return
361                    Objects.equals(this.name, o.name)
362                &&  Objects.equals(this.uuid, o.uuid)
363                &&  Objects.equals(this.baseAddress, o.baseAddress)
364                &&  Objects.equals(this.size, o.size);
365        }
366        
367        /** Generates a Hash-Code for {@code 'this'} instance */
368        public int hashCode()
369        {
370            return
371                    Objects.hashCode(this.name)
372                +   Objects.hashCode(this.uuid)
373                +   Objects.hashCode(this.baseAddress)
374                +   Objects.hashCode(this.size);
375        }
376    }
377    
378    /** DOM object counter data. */
379    public static class DOMCounter
380        extends BaseType
381        implements java.io.Serializable
382    {
383        /** For Object Serialization.  java.io.Serializable */
384        protected static final long serialVersionUID = 1;
385        
386        public boolean[] optionals()
387        { return new boolean[] { false, false, }; }
388        
389        /**
390         * Object name. Note: object names should be presumed volatile and clients should not expect
391         * the returned names to be consistent across runs.
392         */
393        public final String name;
394        
395        /** Object count. */
396        public final int count;
397        
398        /**
399         * Constructor
400         *
401         * @param name 
402         * Object name. Note: object names should be presumed volatile and clients should not expect
403         * the returned names to be consistent across runs.
404         * 
405         * @param count Object count.
406         */
407        public DOMCounter(String name, int count)
408        {
409            // Exception-Check(s) to ensure that if any parameters which are not declared as
410            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
411            
412            if (name == null) THROWS.throwNPE("name");
413            
414            this.name   = name;
415            this.count  = count;
416        }
417        
418        /**
419         * JSON Object Constructor
420         * @param jo A Json-Object having data about an instance of {@code 'DOMCounter'}.
421         */
422        public DOMCounter (JsonObject jo)
423        {
424            this.name   = ReadJSON.getString(jo, "name", false, true);
425            this.count  = ReadPrimJSON.getInt(jo, "count");
426        }
427        
428        
429        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
430        public boolean equals(Object other)
431        {
432            if (this == other)                       return true;
433            if (other == null)                       return false;
434            if (other.getClass() != this.getClass()) return false;
435        
436            DOMCounter o = (DOMCounter) other;
437        
438            return
439                    Objects.equals(this.name, o.name)
440                &&  (this.count == o.count);
441        }
442        
443        /** Generates a Hash-Code for {@code 'this'} instance */
444        public int hashCode()
445        {
446            return
447                    Objects.hashCode(this.name)
448                +   this.count;
449        }
450    }
451    
452    
453    // Counter for keeping the WebSocket Request ID's distinct.
454    private static int counter = 1;
455    
456    /**
457     * Retruns current DOM object counters.
458     * 
459     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
460     * {@link Ret3}&gt;</CODE>
461     *
462     * <BR /><BR />This {@link Script} may be <B STYLE='color:red'>executed</B> (using 
463     * {@link Script#exec()}), and a {@link Promise} returned.
464     *
465     * <BR /><BR />When the {@code Promise} is <B STYLE='color: red'>awaited</B>
466     * (using {@link Promise#await()}), the {@code Ret3} will subsequently
467     * be returned from that call.
468     * 
469     * <BR /><BR />The <B STYLE='color: red'>returned</B> values are encapsulated
470     * in an instance of <B>{@link Ret3}</B>
471     *
472     * <BR /><BR /><UL CLASS=JDUL>
473     * <LI><CODE><B>Ret3.a:</B> Integer (<B>documents</B>)</CODE>
474     *     <BR />-
475     *     <BR /><BR /></LI>
476     * <LI><CODE><B>Ret3.b:</B> Integer (<B>nodes</B>)</CODE>
477     *     <BR />-
478     *     <BR /><BR /></LI>
479     * <LI><CODE><B>Ret3.c:</B> Integer (<B>jsEventListeners</B>)</CODE>
480     *     <BR />-
481     *     </LI>
482     * </UL>
483     */
484    public static Script<String, JsonObject, Ret3<Integer, Integer, Integer>> getDOMCounters()
485    {
486        final int          webSocketID = 32000000 + counter++;
487        final boolean[]    optionals   = new boolean[0];
488        
489        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
490        String requestJSON = WriteJSON.get(
491            parameterTypes.get("getDOMCounters"),
492            parameterNames.get("getDOMCounters"),
493            optionals, webSocketID,
494            "Memory.getDOMCounters"
495        );
496        
497        // 'JSON Binding' ... Converts Browser Response-JSON into Java-Type 'Ret3'
498        Function<JsonObject, Ret3<Integer, Integer, Integer>>
499            responseProcessor = (JsonObject jo) -> new Ret3<>(
500                ReadBoxedJSON.getInteger(jo, "documents", true),
501                ReadBoxedJSON.getInteger(jo, "nodes", true),
502                ReadBoxedJSON.getInteger(jo, "jsEventListeners", true)
503            );
504        
505        return new Script<>(webSocketID, requestJSON, responseProcessor);
506    }
507    
508    /**
509     * Retruns DOM object counters after preparing renderer for leak detection.
510     * 
511     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
512     * {@link Memory.DOMCounter}[]&gt;</CODE>
513     * 
514     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
515     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
516     * {@link Memory.DOMCounter}[]&gt;</CODE> will be returned.
517     *
518     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
519     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
520      * may be retrieved.</I>
521     *
522     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
523     * <BR /><BR /><UL CLASS=JDUL>
524     * <LI><CODE>{@link Memory.DOMCounter}[] (<B>counters</B></CODE>)
525     *     <BR />DOM object counters.
526     * </LI>
527     * </UL> */
528    public static Script<String, JsonObject, Memory.DOMCounter[]> getDOMCountersForLeakDetection()
529    {
530        final int          webSocketID = 32001000 + counter++;
531        final boolean[]    optionals   = new boolean[0];
532        
533        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
534        String requestJSON = WriteJSON.get(
535            parameterTypes.get("getDOMCountersForLeakDetection"),
536            parameterNames.get("getDOMCountersForLeakDetection"),
537            optionals, webSocketID,
538            "Memory.getDOMCountersForLeakDetection"
539        );
540        
541        // 'JSON Binding' ... Converts Browser Response-JSON to 'Memory.DOMCounter[]'
542        Function<JsonObject, Memory.DOMCounter[]> responseProcessor = (JsonObject jo) ->
543            (jo.getJsonArray("counters") == null)
544                ? null
545                : RJArrIntoStream.objArr(jo.getJsonArray("counters"), null, 0, Memory.DOMCounter.class).toArray(Memory.DOMCounter[]::new);
546        
547        return new Script<>(webSocketID, requestJSON, responseProcessor);
548    }
549    
550    /**
551     * Prepares for leak detection by terminating workers, stopping spellcheckers,
552     * dropping non-essential internal caches, running garbage collections, etc.
553     * 
554     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
555     * {@link Ret0}&gt;</CODE>
556     *
557     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
558     * browser receives the invocation-request.
559     *
560     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
561     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
562     * {@code >} to ensure the Browser Function has run to completion.
563     */
564    public static Script<String, JsonObject, Ret0> prepareForLeakDetection()
565    {
566        final int          webSocketID = 32002000 + counter++;
567        final boolean[]    optionals   = new boolean[0];
568        
569        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
570        String requestJSON = WriteJSON.get(
571            parameterTypes.get("prepareForLeakDetection"),
572            parameterNames.get("prepareForLeakDetection"),
573            optionals, webSocketID,
574            "Memory.prepareForLeakDetection"
575        );
576        
577        // This Remote Command does not have a Return-Value.
578        return new Script<>
579            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
580    }
581    
582    /**
583     * Simulate OomIntervention by purging V8 memory.
584     * 
585     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
586     * {@link Ret0}&gt;</CODE>
587     *
588     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
589     * browser receives the invocation-request.
590     *
591     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
592     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
593     * {@code >} to ensure the Browser Function has run to completion.
594     */
595    public static Script<String, JsonObject, Ret0> forciblyPurgeJavaScriptMemory()
596    {
597        final int          webSocketID = 32003000 + counter++;
598        final boolean[]    optionals   = new boolean[0];
599        
600        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
601        String requestJSON = WriteJSON.get(
602            parameterTypes.get("forciblyPurgeJavaScriptMemory"),
603            parameterNames.get("forciblyPurgeJavaScriptMemory"),
604            optionals, webSocketID,
605            "Memory.forciblyPurgeJavaScriptMemory"
606        );
607        
608        // This Remote Command does not have a Return-Value.
609        return new Script<>
610            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
611    }
612    
613    /**
614     * Enable/disable suppressing memory pressure notifications in all processes.
615     * 
616     * @param suppressed If true, memory pressure notifications will be suppressed.
617     * 
618     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
619     * {@link Ret0}&gt;</CODE>
620     *
621     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
622     * browser receives the invocation-request.
623     *
624     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
625     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
626     * {@code >} to ensure the Browser Function has run to completion.
627     */
628    public static Script<String, JsonObject, Ret0> setPressureNotificationsSuppressed
629        (boolean suppressed)
630    {
631        final int       webSocketID = 32004000 + counter++;
632        final boolean[] optionals   = { false, };
633        
634        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
635        String requestJSON = WriteJSON.get(
636            parameterTypes.get("setPressureNotificationsSuppressed"),
637            parameterNames.get("setPressureNotificationsSuppressed"),
638            optionals, webSocketID,
639            "Memory.setPressureNotificationsSuppressed",
640            suppressed
641        );
642        
643        // This Remote Command does not have a Return-Value.
644        return new Script<>
645            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
646    }
647    
648    /**
649     * Simulate a memory pressure notification in all processes.
650     * 
651     * @param level Memory pressure level of the notification.
652     * 
653     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
654     * {@link Ret0}&gt;</CODE>
655     *
656     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
657     * browser receives the invocation-request.
658     *
659     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
660     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
661     * {@code >} to ensure the Browser Function has run to completion.
662     */
663    public static Script<String, JsonObject, Ret0> simulatePressureNotification(String level)
664    {
665        // Exception-Check(s) to ensure that if any parameters which are not declared as
666        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
667        
668        if (level == null) THROWS.throwNPE("level");
669        
670        // Exception-Check(s) to ensure that if any parameters which must adhere to a
671        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
672        
673        THROWS.checkIAE("level", level, "Memory.PressureLevel", Memory.PressureLevel);
674        
675        final int       webSocketID = 32005000 + counter++;
676        final boolean[] optionals   = { false, };
677        
678        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
679        String requestJSON = WriteJSON.get(
680            parameterTypes.get("simulatePressureNotification"),
681            parameterNames.get("simulatePressureNotification"),
682            optionals, webSocketID,
683            "Memory.simulatePressureNotification",
684            level
685        );
686        
687        // This Remote Command does not have a Return-Value.
688        return new Script<>
689            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
690    }
691    
692    /**
693     * Start collecting native memory profile.
694     * 
695     * @param samplingInterval Average number of bytes between samples.
696     * <BR /><B CLASS=Opt>OPTIONAL</B>
697     * 
698     * @param suppressRandomness Do not randomize intervals between samples.
699     * <BR /><B CLASS=Opt>OPTIONAL</B>
700     * 
701     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
702     * {@link Ret0}&gt;</CODE>
703     *
704     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
705     * browser receives the invocation-request.
706     *
707     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
708     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
709     * {@code >} to ensure the Browser Function has run to completion.
710     */
711    public static Script<String, JsonObject, Ret0> startSampling
712        (Integer samplingInterval, Boolean suppressRandomness)
713    {
714        final int       webSocketID = 32006000 + counter++;
715        final boolean[] optionals   = { true, true, };
716        
717        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
718        String requestJSON = WriteJSON.get(
719            parameterTypes.get("startSampling"),
720            parameterNames.get("startSampling"),
721            optionals, webSocketID,
722            "Memory.startSampling",
723            samplingInterval, suppressRandomness
724        );
725        
726        // This Remote Command does not have a Return-Value.
727        return new Script<>
728            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
729    }
730    
731    /**
732     * Stop collecting native memory profile.
733     * 
734     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
735     * {@link Ret0}&gt;</CODE>
736     *
737     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
738     * browser receives the invocation-request.
739     *
740     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
741     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
742     * {@code >} to ensure the Browser Function has run to completion.
743     */
744    public static Script<String, JsonObject, Ret0> stopSampling()
745    {
746        final int          webSocketID = 32007000 + counter++;
747        final boolean[]    optionals   = new boolean[0];
748        
749        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
750        String requestJSON = WriteJSON.get(
751            parameterTypes.get("stopSampling"),
752            parameterNames.get("stopSampling"),
753            optionals, webSocketID,
754            "Memory.stopSampling"
755        );
756        
757        // This Remote Command does not have a Return-Value.
758        return new Script<>
759            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
760    }
761    
762    /**
763     * Retrieve native memory allocations profile
764     * collected since renderer process startup.
765     * 
766     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
767     * {@link Memory.SamplingProfile}&gt;</CODE>
768     * 
769     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
770     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
771     * {@link Memory.SamplingProfile}&gt;</CODE> will be returned.
772     *
773     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
774     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
775      * may be retrieved.</I>
776     *
777     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
778     * <BR /><BR /><UL CLASS=JDUL>
779     * <LI><CODE>{@link Memory.SamplingProfile} (<B>profile</B></CODE>)
780     *     <BR />-
781     * </LI>
782     * </UL> */
783    public static Script<String, JsonObject, Memory.SamplingProfile> getAllTimeSamplingProfile()
784    {
785        final int          webSocketID = 32008000 + counter++;
786        final boolean[]    optionals   = new boolean[0];
787        
788        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
789        String requestJSON = WriteJSON.get(
790            parameterTypes.get("getAllTimeSamplingProfile"),
791            parameterNames.get("getAllTimeSamplingProfile"),
792            optionals, webSocketID,
793            "Memory.getAllTimeSamplingProfile"
794        );
795        
796        // 'JSON Binding' ... Converts Browser Response-JSON to 'Memory.SamplingProfile'
797        Function<JsonObject, Memory.SamplingProfile> responseProcessor = (JsonObject jo) ->
798            ReadJSON.getObject(jo, "profile", Memory.SamplingProfile.class, false, true);
799        
800        return new Script<>(webSocketID, requestJSON, responseProcessor);
801    }
802    
803    /**
804     * Retrieve native memory allocations profile
805     * collected since browser process startup.
806     * 
807     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
808     * {@link Memory.SamplingProfile}&gt;</CODE>
809     * 
810     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
811     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
812     * {@link Memory.SamplingProfile}&gt;</CODE> will be returned.
813     *
814     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
815     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
816      * may be retrieved.</I>
817     *
818     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
819     * <BR /><BR /><UL CLASS=JDUL>
820     * <LI><CODE>{@link Memory.SamplingProfile} (<B>profile</B></CODE>)
821     *     <BR />-
822     * </LI>
823     * </UL> */
824    public static Script<String, JsonObject, Memory.SamplingProfile> getBrowserSamplingProfile()
825    {
826        final int          webSocketID = 32009000 + counter++;
827        final boolean[]    optionals   = new boolean[0];
828        
829        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
830        String requestJSON = WriteJSON.get(
831            parameterTypes.get("getBrowserSamplingProfile"),
832            parameterNames.get("getBrowserSamplingProfile"),
833            optionals, webSocketID,
834            "Memory.getBrowserSamplingProfile"
835        );
836        
837        // 'JSON Binding' ... Converts Browser Response-JSON to 'Memory.SamplingProfile'
838        Function<JsonObject, Memory.SamplingProfile> responseProcessor = (JsonObject jo) ->
839            ReadJSON.getObject(jo, "profile", Memory.SamplingProfile.class, false, true);
840        
841        return new Script<>(webSocketID, requestJSON, responseProcessor);
842    }
843    
844    /**
845     * Retrieve native memory allocations profile collected since last
846     * {@code startSampling} call.
847     * 
848     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
849     * {@link Memory.SamplingProfile}&gt;</CODE>
850     * 
851     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
852     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
853     * {@link Memory.SamplingProfile}&gt;</CODE> will be returned.
854     *
855     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
856     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
857      * may be retrieved.</I>
858     *
859     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
860     * <BR /><BR /><UL CLASS=JDUL>
861     * <LI><CODE>{@link Memory.SamplingProfile} (<B>profile</B></CODE>)
862     *     <BR />-
863     * </LI>
864     * </UL> */
865    public static Script<String, JsonObject, Memory.SamplingProfile> getSamplingProfile()
866    {
867        final int          webSocketID = 32010000 + counter++;
868        final boolean[]    optionals   = new boolean[0];
869        
870        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
871        String requestJSON = WriteJSON.get(
872            parameterTypes.get("getSamplingProfile"),
873            parameterNames.get("getSamplingProfile"),
874            optionals, webSocketID,
875            "Memory.getSamplingProfile"
876        );
877        
878        // 'JSON Binding' ... Converts Browser Response-JSON to 'Memory.SamplingProfile'
879        Function<JsonObject, Memory.SamplingProfile> responseProcessor = (JsonObject jo) ->
880            ReadJSON.getObject(jo, "profile", Memory.SamplingProfile.class, false, true);
881        
882        return new Script<>(webSocketID, requestJSON, responseProcessor);
883    }
884    
885}