snips.sh

   1/// SpiderMonkey 45/52 *.h header port to Delphi
   2// if defined SM52 condition then SpiderMonkey 52 is used
   3// - this unit is a part of the freeware Synopse framework,
   4// licensed under a MPL/GPL/LGPL tri-license; version 1.18
   5unit SpiderMonkey;
   6{
   7    This file is part of Synopse framework.
   8
   9    Synopse framework. Copyright (c) Arnaud Bouchez
  10      Synopse Informatique - http://synopse.info
  11
  12    SyNode for mORMot Copyright (c) Pavel Mashlyakovsky & Vadim Orel
  13      pavel.mash at gmail.com
  14
  15  *** BEGIN LICENSE BLOCK *****
  16  Version: MPL 1.1/GPL 2.0/LGPL 2.1
  17
  18  The contents of this file are subject to the Mozilla Public License Version
  19  1.1 (the "License"); you may not use this file except in compliance with
  20  the License. You may obtain a copy of the License at
  21  http://www.mozilla.org/MPL
  22
  23  Software distributed under the License is distributed on an "AS IS" basis,
  24  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  25  for the specific language governing rights and limitations under the License.
  26
  27  The Initial Developer of the Original Code is
  28  Pavel Mashlyakovsky & Vadim Orel.
  29  Portions created by the Initial Developer are Copyright (c)
  30  the Initial Developer. All Rights Reserved.
  31
  32  Contributor(s):
  33  - Arnaud Bouchez
  34  - Vadim Orel
  35  - Pavel Mashlyakovsky
  36  - win2014
  37
  38  Alternatively, the contents of this file may be used under the terms of
  39  either the GNU General Public License Version 2 or later (the "GPL"), or
  40  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  41  in which case the provisions of the GPL or the LGPL are applicable instead
  42  of those above. If you wish to allow use of your version of this file only
  43  under the terms of either the GPL or the LGPL, and not to allow others to
  44  use your version of this file under the terms of the MPL, indicate your
  45  decision by deleting the provisions above and replace them with the notice
  46  and other provisions required by the GPL or the LGPL. If you do not delete
  47  the provisions above, a recipient may use your version of this file under
  48  the terms of any one of the MPL, the GPL or the LGPL.
  49
  50  ***** END LICENSE BLOCK *****
  51
  52  Version 1.18
  53  - initial release. Use SpiderMonkey 45
  54}
  55
  56{$I Synopse.inc} // define HASINLINE CPU32 CPU64 OWNNORMTOUPPER
  57{$I SyNode.inc}   //define WITHASSERT
  58
  59interface
  60uses
  61  {$ifdef MSWINDOWS}
  62  Windows,
  63  {$endif}
  64  SynCommons,
  65  SynTable,
  66  SynLog,
  67  SysUtils;
  68
  69type
  70  JSUnknown = Pointer; //Use this type for developping. In real case comment it and check than you use only known types
  71{$ifndef UNICODE}
  72  /// 8 bit signed integer type for C APIs
  73  int8 = ShortInt;
  74  /// 8 bit unsigned integer type for C APIs
  75  uint8 = Byte;
  76
  77  /// 16 bit signed integer type for C APIs
  78  int16 = Smallint;
  79  /// 16 bit unsigned integer type for C APIs
  80  uint16 = Word;
  81
  82  /// 32 bit signed integer type for C APIs
  83  int32 = Integer;
  84  /// 32 bit unsigned integer type for C APIs
  85  uint32 = Cardinal;
  86{$endif}
  87{$ifndef ISDELPHIXE2}
  88  uintptr = PtrUInt;
  89{$endif}
  90  uintN = PtrUInt;
  91
  92{.$ifndef FPC}
  93  /// variable type used to store a buffer size (in bytes) for SMAPI
  94  size_t = PtrUInt;
  95{.$endif}
  96  psize_t = ^size_t;
  97  CChar = AnsiChar;
  98  PCChar = PAnsiChar;
  99  CChar16 = WideChar;
 100  PCChar16 = PWideChar;
 101  PPCChar16 = ^PCChar16;
 102
 103{$Z4}
 104  JSType = (
 105    JSTYPE_VOID       = 0, // undefined
 106    JSTYPE_OBJECT     = 1, // object
 107    JSTYPE_FUNCTION   = 2, // function
 108    JSTYPE_STRING     = 3, // string
 109    JSTYPE_NUMBER     = 4, // number
 110    JSTYPE_BOOLEAN    = 5, // boolean
 111    JSTYPE_NULL       = 6, // null
 112    JSTYPE_SYMBOL     = 7, //symbol
 113    JSTYPE_LIMIT      = 8
 114  );
 115
 116  JSGCParamKey = (
 117    // Maximum nominal heap before last ditch GC.
 118    JSGC_MAX_BYTES = 0,
 119    // Number of JS_malloc bytes before last ditch GC.
 120    JSGC_MAX_MALLOC_BYTES = 1,
 121    // Amount of bytes allocated by the GC.
 122    JSGC_BYTES = 3,
 123    // Number of times GC has been invoked. Includes both major and minor GC.
 124    JSGC_NUMBER = 4,
 125    // Max size of the code cache in bytes.
 126    JSGC_MAX_CODE_CACHE_BYTES = 5,
 127    // Select GC mode.
 128    JSGC_MODE = 6,
 129    // Number of cached empty GC chunks.
 130    JSGC_UNUSED_CHUNKS = 7,
 131    // Total number of allocated GC chunks.
 132    JSGC_TOTAL_CHUNKS = 8,
 133    // Max milliseconds to spend in an incremental GC slice.
 134    JSGC_SLICE_TIME_BUDGET = 9,
 135    // Maximum size the GC mark stack can grow to.
 136    JSGC_MARK_STACK_LIMIT = 10,
 137    // GCs less than this far apart in time will be considered 'high-frequency GCs'.
 138    // See setGCLastBytes in jsgc.cpp.
 139    JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11,
 140    // Start of dynamic heap growth.
 141    JSGC_HIGH_FREQUENCY_LOW_LIMIT = 12,
 142    // End of dynamic heap growth.
 143    JSGC_HIGH_FREQUENCY_HIGH_LIMIT = 13,
 144    // Upper bound of heap growth.
 145    JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX = 14,
 146    // Lower bound of heap growth.
 147    JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN = 15,
 148    // Heap growth for low frequency GCs.
 149    JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16,
 150    // If false, the heap growth factor is fixed at 3. If true, it is determined
 151    // based on whether GCs are high- or low- frequency.
 152    JSGC_DYNAMIC_HEAP_GROWTH = 17,
 153    // If true, high-frequency GCs will use a longer mark slice.
 154    JSGC_DYNAMIC_MARK_SLICE = 18,
 155    // Lower limit after which we limit the heap growth.
 156    JSGC_ALLOCATION_THRESHOLD = 19,
 157    // We try to keep at least this many unused chunks in the free chunk pool at
 158    // all times, even after a shrinking GC.
 159    JSGC_MIN_EMPTY_CHUNK_COUNT = 21,
 160    // We never keep more than this many unused chunks in the free chunk pool.
 161    JSGC_MAX_EMPTY_CHUNK_COUNT = 22,
 162    // Whether compacting GC is enabled.
 163    JSGC_COMPACTING_ENABLED = 23
 164    // If true, painting can trigger IGC slices.
 165    ,JSGC_REFRESH_FRAME_SLICES_ENABLED = 24
 166  );
 167
 168  JSGCMode = (
 169    // Perform only global GCs.
 170    JSGC_MODE_GLOBAL = 0,
 171    // Perform per-compartment GCs until too much garbage has accumulated.
 172    JSGC_MODE_COMPARTMENT = 1,
 173    // Collect in short time slices rather than all at once. Implies
 174    // JSGC_MODE_COMPARTMENT.
 175    JSGC_MODE_INCREMENTAL = 2
 176  );
 177
 178  JSVersion = (
 179    /// Run-time version enumeration corresponding to an identified version
 180    JSVERSION_UNKNOWN = -1,
 181    /// Run-time version enumeration corresponding to default version
 182    JSVERSION_DEFAULT = 0,
 183
 184    JSVERSION_ECMA_3  = 148,
 185    /// Run-time version enumeration corresponding to 1.6
 186    JSVERSION_1_6     = 160,
 187    /// Run-time version enumeration corresponding to 1.7
 188    JSVERSION_1_7     = 170,
 189    /// Run-time version enumeration corresponding to 1.8
 190    JSVERSION_1_8     = 180,
 191    /// Run-time version enumeration corresponding to ECMA standard 5, i.e. 1.8.5
 192    JSVERSION_ECMA_5  = 185
 193  );
 194
 195///  This enum is used to select if properties with JSPROP_DEFINE_LATE flag
 196//  should be defined on the object.
 197//  Normal JSAPI consumers probably always want DefineAllProperties here.
 198  JSPropertyDefinitionBehavior = (
 199  DefineAllProperties,
 200  OnlyDefineLateProperties,
 201  DontDefineLateProperties
 202  );
 203/// During global creation, we fire notifications to callbacks registered
 204// via the Debugger API. These callbacks are arbitrary script, and can touch
 205// the global in arbitrary ways. When that happens, the global should not be
 206// in a half-baked state. But this creates a problem for consumers that need
 207// to set slots on the global to put it in a consistent state.
 208// - This API provides a way for consumers to set slots atomically (immediately
 209// after the global is created), before any debugger hooks are fired. It's
 210// unfortunately on the clunky side, but that's the way the cookie crumbles.
 211// - If callers have no additional state on the global to set up, they may pass
 212// |FireOnNewGlobalHook| to JS_NewGlobalObject, which causes that function to
 213// fire the hook as its final act before returning. Otherwise, callers should
 214// pass |DontFireOnNewGlobalHook|, which means that they are responsible for
 215// invoking JS_FireOnNewGlobalObject upon successfully creating the global. If
 216// an error occurs and the operation aborts, callers should skip firing the
 217// hook. But otherwise, callers must take care to fire the hook exactly once
 218// before compiling any script in the global's scope (we have assertions in
 219// place to enforce this). This lets us be sure that debugger clients never miss
 220// breakpoints.
 221  OnNewGlobalHookOption = (
 222    FireOnNewGlobalHook,
 223    DontFireOnNewGlobalHook
 224  );
 225/// Dense index into cached prototypes and class atoms for standard objects.
 226  JSProtoKey = (
 227  JSProto_Null = 0,
 228  JSProto_Object,
 229  JSProto_Function,
 230  JSProto_Array,
 231  JSProto_Boolean,
 232  JSProto_JSON,
 233  JSProto_Date,
 234  JSProto_Math,
 235  JSProto_Number,
 236  JSProto_String,
 237  JSProto_RegExp,
 238  JSProto_Error,
 239  JSProto_InternalError,
 240  JSProto_EvalError,
 241  JSProto_RangeError,
 242  JSProto_ReferenceError,
 243  JSProto_SyntaxError,
 244  JSProto_TypeError,
 245  JSProto_URIError,
 246  JSProto_DebuggeeWouldRun,
 247  JSProto_CompileError,
 248  JSProto_RuntimeError,
 249  JSProto_Iterator,
 250  JSProto_StopIteration,
 251  JSProto_ArrayBuffer,
 252  JSProto_Int8Array,
 253  JSProto_Uint8Array,
 254  JSProto_Int16Array,
 255  JSProto_Uint16Array,
 256  JSProto_Int32Array,
 257  JSProto_Uint32Array,
 258  JSProto_Float32Array,
 259  JSProto_Float64Array,
 260  JSProto_Uint8ClampedArray,
 261  JSProto_Proxy,
 262  JSProto_WeakMap,
 263  JSProto_Map,
 264  JSProto_Set,
 265  JSProto_DataView,
 266  JSProto_Symbol,
 267  JSProto_SharedArrayBuffer,
 268  JSProto_Intl,
 269  JSProto_TypedObject,
 270  JSProto_Reflect,
 271  JSProto_SIMD,
 272  JSProto_WeakSet,
 273  JSProto_TypedArray,
 274  JSProto_Atomics,
 275  JSProto_SavedFrame,
 276  JSProto_WebAssembly,
 277  JSProto_WasmModule,
 278  JSProto_WasmInstance,
 279  JSProto_WasmMemory,
 280  JSProto_WasmTable,
 281  JSProto_Promise,
 282  JSProto_LIMIT
 283  );
 284{$Z1}
 285/// Type of JSValue
 286  JSValueType = (
 287    JSVAL_TYPE_DOUBLE   = $00,
 288    JSVAL_TYPE_INT32    = $01,
 289    JSVAL_TYPE_UNDEFINED= $02,
 290    JSVAL_TYPE_BOOLEAN  = $03,
 291    JSVAL_TYPE_MAGIC    = $04,
 292    JSVAL_TYPE_STRING   = $05,
 293    JSVAL_TYPE_SYMBOL   = $06,
 294    JSVAL_TYPE_PRIVATE_GCTHING = $07,
 295    JSVAL_TYPE_NULL     = $08,
 296    JSVAL_TYPE_OBJECT   = $0C,
 297    // These never appear in a jsval; they are only provided as an out-of-band value.
 298    JSVAL_TYPE_UNKNOWN  = $20,
 299    JSVAL_TYPE_MISSING  = $21
 300  );
 301
 302{$ifndef CPU64}
 303/// first 4 bytes for JSValue
 304{$MINENUMSIZE 4}
 305{$WARN COMBINING_SIGNED_UNSIGNED OFF}
 306{$WARN BOUNDS_ERROR OFF}
 307  JSValueTag = (
 308  JSVAL_TAG_CLEAR      = Cardinal($FFFFFF80),
 309  JSVAL_TAG_INT32      = Cardinal(JSVAL_TAG_CLEAR or UInt8(JSVAL_TYPE_INT32)),
 310  JSVAL_TAG_UNDEFINED  = Cardinal(JSVAL_TAG_CLEAR or UInt8(JSVAL_TYPE_UNDEFINED)),
 311  JSVAL_TAG_STRING     = Cardinal(JSVAL_TAG_CLEAR or UInt8(JSVAL_TYPE_STRING)),
 312  JSVAL_TAG_SYMBOL     = Cardinal(JSVAL_TAG_CLEAR or UInt8(JSVAL_TYPE_SYMBOL)),
 313  JSVAL_TAG_BOOLEAN    = Cardinal(JSVAL_TAG_CLEAR or UInt8(JSVAL_TYPE_BOOLEAN)),
 314  JSVAL_TAG_MAGIC      = Cardinal(JSVAL_TAG_CLEAR or UInt8(JSVAL_TYPE_MAGIC)),
 315  JSVAL_TAG_NULL       = Cardinal(JSVAL_TAG_CLEAR or UInt8(JSVAL_TYPE_NULL)),
 316  JSVAL_TAG_OBJECT     = Cardinal(JSVAL_TAG_CLEAR or UInt8(JSVAL_TYPE_OBJECT))
 317  );
 318{$WARN BOUNDS_ERROR ON}
 319{$WARN COMBINING_SIGNED_UNSIGNED ON}
 320{$MINENUMSIZE 1}
 321{$endif}
 322
 323
 324{$Z2}
 325  /// Possible exception types
 326  // -These types are part of a JSErrorFormatString structure
 327  // - They define which error to throw in case of a runtime error
 328  // - JSEXN_NONE marks an unthrowable error
 329  JSExnType = (
 330    JSEXN_NONE = -1,
 331    JSEXN_ERR,
 332    JSEXN_INTERNALERR,
 333    JSEXN_EVALERR,
 334    JSEXN_RANGEERR,
 335    JSEXN_REFERENCEERR,
 336    JSEXN_SYNTAXERR,
 337    JSEXN_TYPEERR,
 338    JSEXN_URIERR,
 339    JSEXN_DEBUGGEEWOULDRUN,
 340    JSEXN_WASMCOMPILEERROR,
 341    JSEXN_WASMRUNTIMEERROR,
 342    JSEXN_WARN,
 343    JSEXN_LIMIT
 344  );
 345{$Z1}
 346
 347
 348  Tint8Vector = array[0..(MaxInt div sizeof(int8))-1] of int8;
 349  Pint8Vector = ^Tint8Vector;
 350  Tuint8Vector = array[0..(MaxInt div sizeof(uint8))-1] of uint8;
 351  Puint8Vector = ^Tuint8Vector;
 352  Tint16Vector = array[0..(MaxInt div sizeof(int16))-1] of int16;
 353  Pint16Vector = ^Tint16Vector;
 354  Tuint16Vector = array[0..(MaxInt div sizeof(uint16))-1] of uint16;
 355  Puint16Vector = ^Tuint16Vector;
 356  Tint32Vector = array[0..(MaxInt div sizeof(int32))-1] of int32;
 357  Pint32Vector = ^Tint32Vector;
 358  Tuint32Vector = array[0..(MaxInt div sizeof(uint32))-1] of uint32;
 359  Puint32Vector = ^Tuint32Vector;
 360  Tfloat32Vector = array[0..(MaxInt div sizeof(single))-1] of single;
 361  Pfloat32Vector = ^Tfloat32Vector;
 362  Tfloat64Vector = array[0..(MaxInt div sizeof(double))-1] of double;
 363  Pfloat64Vector = ^Tfloat64Vector;
 364
 365  /// the available types of elements in a typed array or data view
 366  // - obj must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
 367  // be known that it would pass such a test: it is an ArrayBufferView or a
 368  // wrapper of an ArrayBufferView, and the unwrapping will succeed.
 369  /// - jsabTYPE_UINT8_CLAMPED is a special type that is a uint8_t, but assignments
 370  // are clamped to [0,255]: treat the raw data type as a uint8_t.
 371  // - jsabTYPE_DATAVIEW is the type returned for a DataView. Note that
 372  // there is no single element type in this case
 373  JSArrayBufferViewType = (
 374    jsabTYPE_INT8 = 0,
 375    jsabTYPE_UINT8,
 376    jsabTYPE_INT16,
 377    jsabTYPE_UINT16,
 378    jsabTYPE_INT32,
 379    jsabTYPE_UINT32,
 380    jsabTYPE_FLOAT32,
 381    jsabTYPE_FLOAT64,
 382    jsabTYPE_UINT8_CLAMPED,
 383    jsabTYPE_MAXTYPEDARRAYVIEWTYPE,
 384    jsabTYPE_FLOAT32x4,
 385    jsabTYPE_INT32x4
 386
 387);
 388const
 389  nullPtr: pointer = nil;
 390  /// Run-time version enumeration corresponding to the latest available
 391  // - that is, ECMA standard 5, i.e. 1.8.5
 392  JSVERSION_LATEST  = JSVERSION_ECMA_5;
 393type
 394// pointers
 395  JSFreeOp = pointer;
 396  PJSContextOptions = ^JSContextOptions;
 397  PJSContext = ^JSContext;
 398  PJSCompartment = ^JSCompartment;
 399  PJS_CompartmentOptions = ^JS_CompartmentOptions;
 400  PJSObject = ^JSObject;
 401  PJSFunction = PJSObject;
 402  PJSString = ^JSString;
 403  PJSClass = ^JSClass;
 404  PJSCompileOptions = ^JSCompileOptions;
 405  PJSScript = JSUnknown;
 406  PJSRootedValue = ^JSRootedValue;
 407  PJSRootedObject = ^JSRootedObject;
 408  PJSRootedString = ^JSRootedString;
 409  PJSPropertySpec = ^JSPropertySpec;
 410  PJSFunctionSpec = ^JSFunctionSpec;
 411  PJSErrorReport = ^JSErrorReport;
 412  PJSErrorFormatString = ^JSErrorFormatString;
 413  PJSAtomState = JSUnknown;
 414  PJSPrincipals = JSUnknown;
 415  PJSAutoCheckCannotGC = JSUnknown;
 416  PJSStringFinalizer = ^JSStringFinalizer;
 417
 418// jsid
 419  JSIdType = (
 420    JSID_TYPE_STRING = $0,
 421    JSID_TYPE_INT    = $1,
 422    JSID_TYPE_VOID   = $2,
 423    JSID_TYPE_SYMBOL = $4
 424  );
 425  jsid = record
 426    asBits: size_t;
 427    function isString: Boolean;
 428    function asJSString: PJSString;
 429  end;
 430
 431  TjsidVector = array[0..(MaxInt div sizeof(jsid))-2] of jsid;
 432  PjsidVector = ^TjsidVector;
 433
 434  _JSIdArray = record
 435    cx: PJSContext;
 436    mBegin: PjsidVector;    //* actually, length jsid words */
 437    mLength: size_t;
 438    mCapacity: size_t;
 439    mStorage: Int64;
 440  end;
 441  _JSIdArrayPtr = ^_JSIdArray;
 442/// internal Spidermonkey structure for storrage jsid
 443
 444  { JSIdArray }
 445
 446  JSIdArray  = {$ifdef USERECORDWITHMETHODS}record{$else}object{$endif}
 447  end;
 448  PJSIdArray = ^JSIdArray;
 449
 450// jsvalue
 451  JSWhyMagic = Cardinal;
 452  jsval_payload = record
 453    case Byte of
 454      0: (i32: int32);
 455      1: (u32: uint32);
 456{$IFNDEF CPU64}
 457      2: (boo: uint32);   // Don't use |bool| -- it must be four bytes.
 458      3: (str: PJSString);
 459      4: (obj: PJSObject);
 460      5: (ptr: pointer);
 461{$ENDIF}
 462      6: (why: JSWhyMagic);
 463{$IFNDEF CPU64}
 464      7: (word: size_t);
 465      8: (uintptr: PtrUInt)
 466{$ENDIF}
 467  end;
 468{$ifdef IS_LITTLE_ENDIAN}
 469  jsval_val_layout = packed record
 470    payload: jsval_payload;
 471{$IFNDEF CPU64}
 472    tag: JSValueTag;
 473{$ENDIF}
 474  end;
 475{$else} //BIG_ENDIAN
 476  jsval_val_layout = record
 477    tag: JSValueTag;
 478    payload: jsval_payload;
 479  end;
 480{$endif}
 481
 482  /// low-level definition of the jsval internals
 483  // - do not use directly
 484  jsval_layout = record
 485    case Byte of
 486      0: (asBits: QWord);
 487{$IFNDEF CPU64}
 488      1: (s: jsval_val_layout);
 489{$ENDIF}
 490      2: (asDouble: double);
 491      3: (asPtr: Pointer);
 492  end;
 493
 494  /// used by JS_Stringify() method to incremently write the JSON content
 495  JSONWriteCallback = function(const buf: PCChar16; len: uint32; data: pointer): Boolean; cdecl;
 496
 497  /// high-level definition of the JSValue
 498  {$ifdef USERECORDWITHMETHODS}jsval = record
 499    {$else}jsval = object{$endif}
 500  private
 501    _l: jsval_layout;
 502
 503    function getIsVoid: Boolean; {$ifdef HASINLINE}inline;{$endif}
 504    function getIsNull: Boolean; {$ifdef HASINLINE}inline;{$endif}
 505
 506    function getIsInteger: Boolean; {$ifdef HASINLINE}inline;{$endif}
 507    function getAsInteger: Integer; {$ifdef HASINLINE}inline;{$endif}
 508    procedure setAsInteger(const Value: Integer); {$ifdef HASINLINE}inline;{$endif}
 509
 510    function getAsInt64: Int64; {$ifdef HASINLINE}inline;{$endif}
 511    procedure setAsInt64(const Value: Int64); {$ifdef HASINLINE}inline;{$endif}
 512
 513    function getIsDouble: Boolean;{$ifdef HASINLINE}inline;{$endif}
 514    function getAsDouble: Double;{$ifdef HASINLINE}inline;{$endif}
 515    procedure setAsDouble(const Value: Double);{$ifdef HASINLINE}inline;{$endif}
 516
 517    function getIsNumber: Boolean;{$ifdef HASINLINE}inline;{$endif}
 518
 519    function getIsBoolean: Boolean;{$ifdef HASINLINE}inline;{$endif}
 520    function getAsBoolean: Boolean;{$ifdef HASINLINE}inline;{$endif}
 521    procedure setAsBoolean(const Value: Boolean);{$ifdef HASINLINE}inline;{$endif}
 522
 523    function getIsObject: Boolean;{$ifdef HASINLINE}inline;{$endif}
 524    function getAsObject: PJSObject;{$ifdef HASINLINE}inline;{$endif}
 525    procedure setAsObject(const Value: PJSObject);{$ifdef HASINLINE}inline;{$endif}
 526
 527    function getIsString: Boolean; {$ifdef HASINLINE}inline;{$endif}
 528    function getJSString: PJSString; {$ifdef HASINLINE}inline;{$endif}
 529    procedure setJSString(const Value: PJSString);{$ifdef HASINLINE}inline;{$endif}
 530
 531    function getIsSimpleVariant(cx: PJSContext): Boolean;{$ifdef HASINLINE}inline;{$endif}
 532    function getSimpleVariant(cx: PJSContext): Variant;
 533    procedure setSimpleVariant(cx: PJSContext; const Value: Variant);
 534
 535    function getPrivate: Pointer;{$ifdef HASINLINE}inline;{$endif}
 536    procedure setPrivate(const Value: Pointer);{$ifdef HASINLINE}inline;{$endif}
 537
 538    function getAsDate(cx: PJSContext): TDateTime;
 539    procedure setAsDate(cx: PJSContext; const Value: TDateTime);
 540
 541    function getAsJson(cx: PJSContext): RawUTF8;
 542    procedure setAsJson(cx: PJSContext; const Value: RawUTF8);
 543
 544    function IsPrimitive: Boolean;{$ifdef HASINLINE}inline;{$endif}
 545    function IsMagic: Boolean;{$ifdef HASINLINE}inline;{$endif}
 546
 547  public
 548    /// Is vaule void
 549    property isVoid: Boolean read getIsVoid;
 550    /// Set vaule void
 551    procedure setVoid;
 552    /// Is vaule null
 553    property isNull: Boolean read getIsNull;
 554    /// Set vaule null
 555    procedure setNull;
 556    /// Is vaule 32bit integer
 557    property isInteger: Boolean read getIsInteger;
 558    /// Get/set vaule as 32bit integer
 559    property asInteger: Integer read getAsInteger write setAsInteger;
 560    /// Get/set vaule as 64bit integer (if more than 32 bits than as double)
 561    property asInt64: Int64 read getAsInt64 write setAsInt64;
 562    /// Is vaule double
 563    property isDouble: Boolean read getIsDouble;
 564    /// Get/set vaule as double
 565    property asDouble: Double read getAsDouble write setAsDouble;
 566    /// Is vaule Number (32bit integer or double)
 567    property isNumber: Boolean read getIsNumber;
 568    /// Is vaule boolean
 569    property isBoolean: Boolean read getIsBoolean;
 570    /// Get/set vaule as boolean
 571    property asBoolean: Boolean read getAsBoolean write setAsBoolean;
 572    /// Is vaule object(null is object too)
 573    property isObject: Boolean read getIsObject;
 574    /// Get/set vaule as object
 575    property asObject: PJSObject read getAsObject write setAsObject;
 576    /// Is vaule string
 577    property isString: Boolean read getIsString;
 578    /// Get/set vaule as JSString
 579    property asJSString: PJSString read getJSString write setJSString;
 580    /// Is vaule simple(void, null, boolean, number or string)
 581    property isSimpleVariant[cx: PJSContext]: Boolean read getIsSimpleVariant;
 582    /// Get/set vaule as simple
 583    property asSimpleVariant[cx: PJSContext]: Variant read getSimpleVariant write setSimpleVariant;
 584    /// Get/set vaule as Custom pointer
 585    property asPrivate: Pointer read getPrivate write setPrivate;
 586    /// Get/set vaule as DateTime(object Date used)
 587    property asDate[cx: PJSContext]: TDateTime read getAsDate write setAsDate;
 588    /// Add JSON representation of value to Writer
 589    procedure AddJSON(cx: PJSContext; W: TTextWriter);
 590    /// Get/set vaule as JSON representation
 591    property asJson[cx: PJSContext]: RawUTF8 read getAsJson write setAsJson;
 592    /// Get JSON representation of value and launch callback
 593    function Stringify(cx: PJSContext; var replacer: PJSObject; space: jsval;
 594      callback: JSONWriteCallback; data: pointer): Boolean;
 595    /// Get type of value
 596    function ValType(cx: PJSContext): JSType;
 597    /// Get source of value
 598    function toSource(cx: PJSContext): PJSString;
 599    /// jsval.*Value functions cunstruct new jsval as in JS::Value C++
 600    // classes - see https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_Reference/JS::Value
 601    class function NullValue: jsval; static; {$ifdef HASINLINE}inline;{$endif}
 602    class function Int32Value(v: integer): jsval; static; {$ifdef HASINLINE}inline;{$endif}
 603    class function BooleanValue(v: boolean): jsval; static; {$ifdef HASINLINE}inline;{$endif}
 604    class function TrueValue: jsval; static; {$ifdef HASINLINE}inline;{$endif}
 605    class function FalseValue: jsval; static; {$ifdef HASINLINE}inline;{$endif}
 606    class function DoubleValue(v: double): jsval; static; {$ifdef HASINLINE}inline;{$endif}
 607    class function StringValue(v: PJSString): jsval; static; {$ifdef HASINLINE}inline;{$endif}
 608    class function ObjectValue(v: PJSObject): jsval; static; {$ifdef HASINLINE}inline;{$endif}
 609    // SyNode extension (not present in original C++)
 610    class function Int64Value(v: Int64): jsval; static; {$ifdef HASINLINE}inline;{$endif}
 611  end;
 612
 613  /// an abstract array of jsval JavaScript values
 614  TjsvalVector = array[0..(MaxInt div sizeof(jsval))-3] of jsval;
 615  /// map an array of jsval JavaScript values
 616  PjsvalVector = ^TjsvalVector;
 617  TjsvalDynArray = array of jsval;
 618
 619  /// low-level definition of arguments of function
 620  // - do not use it dirrectly
 621  _JSArgRec = record
 622    case boolean of
 623      true: (
 624        calle: jsval;
 625        this: jsval;
 626        argv: jsval;
 627      );
 628      false: (rval: jsval);
 629  end;
 630
 631  /// hight-level definition of arguments of function
 632  {$ifdef USERECORDWITHMETHODS}JSArgRec = record
 633    {$else}JSArgRec = object{$endif}
 634  private
 635    rec: _JSArgRec;
 636    function GetIsConstructing: Boolean; {$ifdef HASINLINE}inline;{$endif}
 637    function getThis(cx: PJSContext): jsval; {$ifdef HASINLINE}inline;{$endif}
 638    function getThisObject(cx: PJSContext): PJSObject;
 639    function getArgv: PjsvalVector; {$ifdef HASINLINE}inline;{$endif}
 640    function getCalleObject: PJSObject; {$ifdef HASINLINE}inline;{$endif}
 641  public
 642  /// is function called as constructor
 643    property IsConstructing: Boolean read GetIsConstructing;
 644  /// function, that is called now
 645    property calle: jsval read rec.calle;
 646    property calleObject: PJSObject read getCalleObject;
 647  /// this value of function
 648    property this[cx: PJSContext]: jsval read getThis;
 649    property thisObject[cx: PJSContext]: PJSObject read getThisObject;
 650  /// arguments of function
 651    property argv: PjsvalVector read getArgv;
 652  /// return value of function
 653    property rval: jsval read rec.rval write rec.rval;
 654  end;
 655
 656//Todo - set correct codes for some sitautions
 657  JS_ObjectOpResult = object
 658    code: UIntPtr;
 659  end;
 660
 661// callback
 662  JSInterruptCallback = function(cx: PJSContext): Boolean; cdecl;
 663  /// callback prototype for returning an execution error
 664  JSErrorCallback = function(userRef: Pointer; const errorNumber: uintN): PJSErrorFormatString; cdecl;
 665  /// callback prototype for reporting error for a given runtime context
 666  JSWarningReporter = procedure(cx: PJSContext; report: PJSErrorReport); cdecl;
 667  JSStringFinalizerOp = procedure(fin: PJSStringFinalizer; chars: PCChar16);  cdecl;
 668
 669// Add or get a property named by id in obj.  Note the jsid id type -- id may
 670// be a string (Unicode property identifier) or an int (element index).  The
 671// *vp out parameter, on success, is the new property value after the action.
 672  JSAddPropertyOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid;
 673    out vp: jsval): Boolean; cdecl;
 674// Delete a property named by id in obj.
 675// - If an error occurred, return false as per normal JSAPI error practice.
 676// - If no error occurred, but the deletion attempt wasn't allowed (perhaps
 677// because the property was non-configurable), set *succeeded to false and
 678// return true.  This will cause |delete obj[id]| to evaluate to false in
 679// non-strict mode code, and to throw a TypeError in strict mode code.
 680// - If no error occurred and the deletion wasn't disallowed (this is *not* the
 681// same as saying that a deletion actually occurred -- deleting a non-existent
 682// property, or an inherited property, is allowed -- it's just pointless),
 683// set *succeeded to true and return true.
 684  JSDeletePropertyOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid;
 685    out res: JS_ObjectOpResult):Boolean; cdecl;
 686// Get a property named by id in obj.  Note the jsid id type -- id may
 687// be a string (Unicode property identifier) or an int (element index).  The
 688// *vp out parameter, on success, is the new property value after the action.
 689  JSGetterOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid; out vp: jsval):Boolean; cdecl;
 690// Set a property named by id in obj, treating the assignment as strict
 691// mode code if strict is true. Note the jsid id type -- id may be a string
 692// (Unicode property identifier) or an int (element index). The *vp out
 693// parameter, on success, is the new property value after the
 694// set.
 695  JSSetterOp  = function(cx: PJSContext; var obj: PJSObject; var id: jsid;
 696    var vp: jsval; out res: JS_ObjectOpResult):Boolean; cdecl;
 697// The old-style JSClass.enumerate op should define all lazy properties not
 698// yet reflected in obj.
 699  JSEnumerateOp = function(cx: PJSContext; var obj: PJSObject): Boolean; cdecl;
 700// Resolve a lazy property named by id in obj by defining it directly in obj.
 701// Lazy properties are those reflected from some peer native property space
 702// (e.g., the DOM attributes for a given node reflected as obj) on demand.
 703// - JS looks for a property in an object, and if not found, tries to resolve
 704// the given id. *resolvedp should be set to true iff the property was
 705// was defined on |obj|.
 706  JSResolveOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid; out resolved: Boolean): Boolean; cdecl;
 707// A class with a resolve hook can optionally have a mayResolve hook. This hook
 708// must have no side effects and must return true for a given id if the resolve
 709// hook may resolve this id. This is useful when we're doing a "pure" lookup: if
 710// mayResolve returns false, we know we don't have to call the effectful resolve
 711// hook.
 712//
 713// maybeObj, if non-null, is the object on which we're doing the lookup. This
 714// can be nullptr: during JIT compilation we sometimes know the Class but not
 715// the object.
 716  JSMayResolveOp = function(names: PJSAtomState; id: jsid; maybeObj: PJSObject): Boolean; cdecl;
 717  JSFinalizeOp = procedure(var fop: JSFreeOp; obj: PJSObject); cdecl;
 718// Check whether v is an instance of obj.  Return false on error or exception,
 719// true on success with true in *bp if v is an instance of obj, false in
 720// *bp otherwise.
 721  JSHasInstanceOp = function(cx: PJSContext; var obj: PJSObject; var vp: jsval; out b: Boolean): Boolean; cdecl;
 722// Typedef for native functions called by the JS VM.
 723  JSNative = function(cx: PJSContext; argc: uintN; var vp: JSArgRec): Boolean; cdecl;
 724// Function type for trace operation of the class called to enumerate all
 725// traceable things reachable from obj's private data structure. For each such
 726// thing, a trace implementation must call one of the JS_Call*Tracer variants
 727// on the thing.
 728//
 729// JSTraceOp implementation can assume that no other threads mutates object
 730// state. It must not change state of the object or corresponding native
 731// structures. The only exception for this rule is the case when the embedding
 732// needs a tight integration with GC. In that case the embedding can check if
 733// the traversal is a part of the marking phase through calling
 734// JS_IsGCMarkingTracer and apply a special code like emptying caches or
 735// marking its native structures.
 736  JSTraceOp = JSUnknown;
 737
 738/// Options of context
 739  JSContextOptions = object
 740  private
 741    function getOptions(const Index: Integer): Boolean;
 742    procedure setOptions(const Index: Integer; const Value: Boolean);
 743  public
 744    property Baseline: Boolean index 0 read getOptions write setOptions;
 745    property Ion: Boolean index 1 read getOptions write setOptions;
 746    property AsmJS: Boolean index 2 read getOptions write setOptions;
 747    property Wasm: Boolean index 3 read getOptions write setOptions;
 748    property WasmAlwaysBaseline: Boolean index 4 read getOptions write setOptions;
 749    property ThrowOnAsmJSValidationFailure: Boolean index 5 read getOptions write setOptions;
 750    property NativeRegExp: Boolean index 6 read getOptions write setOptions;
 751    property UnboxedArrays: Boolean index 7 read getOptions write setOptions;
 752    property AsyncStack: Boolean index 8 read getOptions write setOptions;
 753    property ThrowOnDebuggeeWouldRun: Boolean index 9 read getOptions write setOptions;
 754    property Werror: Boolean index 10 read getOptions write setOptions;
 755    property StrictMode: Boolean index 11 read getOptions write setOptions;
 756    property ExtraWarnings: Boolean index 12 read getOptions write setOptions;
 757  end;
 758  /// JavaScript execution context
 759  // - this object does not store anything, but just provide some helper methods
 760
 761  { JSContext }
 762
 763  JSContext = object
 764  private
 765    function GetPrivate: Pointer; {$ifdef HASINLINE}inline;{$endif}
 766    procedure SetPrivate(const Value: Pointer);{$ifdef HASINLINE}inline;{$endif}
 767    function GetEmptyString: PJSString; {$ifdef HASINLINE}inline;{$endif}
 768    function GetGCParameter(key: JSGCParamKey): uint32; {$ifdef HASINLINE}inline;{$endif}
 769    procedure SetGCParameter(key: JSGCParamKey; const Value: uint32); {$ifdef HASINLINE}inline;{$endif}
 770    function GetNowMs: int64; {$ifdef HASINLINE}inline;{$endif}
 771    function GetWarningReporter: JSWarningReporter; {$ifdef HASINLINE}inline;{$endif}
 772    procedure SetWarningReporter(reporter: JSWarningReporter); {$ifdef HASINLINE}inline;{$endif}
 773    function GetOptions: PJSContextOptions; {$ifdef HASINLINE}inline;{$endif}
 774    function GetIsRunning: boolean; {$ifdef HASINLINE}inline;{$endif}
 775  protected
 776    // Return the ArrayBuffer underlying an ArrayBufferView
 777    // - If the buffer has been neutered, this will still return the neutered buffer.
 778    // - obj must be an object that would return true for JS_IsArrayBufferViewObject()
 779    function GetArrayBufferViewBuffer(var obj: PJSObject; out isSharedMemory: Boolean): PJSObject; overload;{$ifdef HASINLINE}inline;{$endif}
 780    function GetArrayBufferViewBuffer(var obj: PJSObject): PJSObject; overload;{$ifdef HASINLINE}inline;{$endif}
 781  public
 782    /// Initializes the JavaScript context.
 783    class function CreateNew(maxbytes: uint32; maxNurseryBytes: uint32 = 16 * (1 SHL 20); parentContext: PJSContext = nil): PJSContext; static;
 784    /// Performs garbage collection in the JS memory pool.
 785    procedure GC; {$ifdef HASINLINE}inline;{$endif}
 786    /// Returns the empty string as a JSString object.
 787    property EmptyString: PJSString read GetEmptyString;
 788    /// Get/Set performance parameters related to garbage collection.
 789    property GCParameter[key: JSGCParamKey]: uint32 read GetGCParameter write SetGCParameter;
 790    /// Adjust performance parameters related to garbage collection based on available memory(in megabytes).
 791    procedure SetGCParametersBasedOnAvailableMemory(availMem: uint32);
 792    /// Microseconds since the epoch, midnight, January 1, 1970 UTC.
 793    property NowMs: int64 read GetNowMs;
 794    /// Request a callback set using JS_SetInterruptCallback
 795    procedure RequestInterruptCallback; {$ifdef HASINLINE}inline;{$endif}
 796    /// Set the size of the native stack that should not be exceed. To disable
 797    // stack size checking pass 0.
 798    // - SpiderMonkey allows for a distinction between system code (such as GCs, which
 799    // may incidentally be triggered by script but are not strictly performed on
 800    // behalf of such script), trusted script (as determined by JS_SetTrustedPrincipals),
 801    // and untrusted script. Each kind of code may have a different stack quota,
 802    // allowing embedders to keep higher-priority machinery running in the face of
 803    // scripted stack exhaustion by something else.
 804    // - The stack quotas for each kind of code should be monotonically descending,
 805    // and may be specified with this function. If 0 is passed for a given kind
 806    // of code, it defaults to the value of the next-highest-priority kind.
 807    // - This function may only be called immediately after the runtime is initialized
 808    // and before any code is executed and/or interrupts requested.
 809    procedure SetNativeStackQuota(systemCodeStackSize: size_t); {$ifdef HASINLINE}inline;{$endif}
 810    /// Get options of context
 811    property Options: PJSContextOptions read GetOptions;
 812    /// Get/Set the warning reporting mechanism for an application.
 813    property WarningReporter: JSWarningReporter read GetWarningReporter write SetWarningReporter;
 814    /// Add callback for interrupt
 815    procedure AddInterruptCallback(callback: JSInterruptCallback); {$ifdef HASINLINE}inline;{$endif}
 816    /// Disable interrupt callbacks call
 817    procedure DisableInterruptCallback; {$ifdef HASINLINE}inline;{$endif}
 818    /// Disable/enable interrupt callbacks call
 819    procedure ResetInterruptCallback(disable: boolean); {$ifdef HASINLINE}inline;{$endif}
 820    /// Call interrupt callback if it is requested
 821    function CheckForInterrupt: Boolean; {$ifdef HASINLINE}inline;{$endif}
 822    /// Read/Write access a JSContext field for application-specific data.
 823    // Memory management for this private data is the application's responsibility.
 824    // The JavaScript engine itself never uses it.
 825    property PrivateData: Pointer read GetPrivate write SetPrivate;
 826    /// Enter a different compartment on the given context, so that objects in that
 827    // compartment can be accessed.
 828    // - NB: This API is infallible; a NULL return value does not indicate error
 829    function EnterCompartment(target: PJSObject): PJSCompartment;{$ifdef HASINLINE}inline;{$endif}
 830    /// Leave a the compartment, returning to the compartment active before the
 831    // corresponding JS_EnterCompartment.
 832    procedure LeaveCompartment(oldCompartment: PJSCompartment);{$ifdef HASINLINE}inline;{$endif}
 833    /// indicates to the JS engine that the calling thread is entering a region
 834    // of code that may call into the JSAPI but does not block
 835    procedure BeginRequest; {$ifdef HASINLINE}inline;{$endif}
 836    /// indicates to the JS engine that the calling thread is leaving a region
 837    // of code that may call into the JSAPI but does not block
 838    procedure EndRequest; {$ifdef HASINLINE}inline;{$endif}
 839    /// Create Compile Options
 840    function NewCompileOptions: PJSCompileOptions;
 841    /// Free Compile Options
 842    procedure FreeCompileOptions(opt: PJSCompileOptions);
 843
 844    /// Create a new JavaScript object for use as a global object.
 845    function NewGlobalObject(clasp: PJSClass;
 846      hookOption: OnNewGlobalHookOption = DontFireOnNewGlobalHook): PJSObject;
 847    /// Initialize standard JS class constructors, prototypes, and any top-level
 848    // functions and constants associated with the standard classes (e.g. isNaN
 849    // for Number).
 850    // - NB: This sets cx's global object to obj if it was null.
 851    function InitStandardClasses(var obj: PJSObject): boolean;
 852    /// Add 'Reflect.parse', a SpiderMonkey extension, to the Reflect object on the
 853    // given global.
 854    function InitReflectParse(var obj: PJSObject): boolean;
 855    /// Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes'
 856    // object will be sealed.
 857    function InitCTypesClass(var obj: PJSObject): boolean;
 858    /// Initialize the 'Debugger' object on a global variable 'obj'. The 'ctypes'
 859    // object will be sealed.
 860    function DefineDebuggerObject(var obj: PJSObject): boolean;
 861    /// This function makes a cross-compartment wrapper for the given JS object.
 862    // Details see here http://stackoverflow.com/questions/18730477/what-does-js-wrapobject-do
 863    function WrapObject(var obj: PJSObject): boolean;
 864
 865    ///// modules support
 866
 867    /// Initialize modeles classes next 2 functions cannot work without calling this function
 868    function InitModuleClasses(var obj: PJSObject): boolean;
 869    /// Compile script as module
 870    function CompileModule(var obj: PJSObject; opts: PJSCompileOptions;
 871       chars: PCChar16; length: size_t): PJSObject;
 872    /// Set handler for module resolving
 873    procedure SetModuleResolveHook(var hook: PJSFunction);
 874
 875
 876    /// Invoke a constructor, like the JS expression `new ctor(...args)`. Returns
 877    // the new object, or null on error.
 878    function New(var ctor: PJSObject; argc: uintN; argv: PjsvalVector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
 879    /// Create a new object based on a specified class and root it
 880    function NewObject(clasp: PJSClass): PJSObject;{$ifdef HASINLINE}inline;{$endif}
 881    /// Create a new object based on a specified class
 882    // - Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
 883    // proto. If proto is nullptr, the JS object will have `null` as [[Prototype]].
 884    function NewObjectWithGivenProto(clasp: PJSClass; var proto: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
 885
 886    /// Create/Free rooted value(put value in rooting stack)
 887    // Garbage collection not performs to rooted values
 888    // - Warning!!! You must free rooted values in revers order for creating
 889    // that's why it's a bad idea store rooting values in any place except
 890    // local variables. Exception is root some values just after creating context
 891    // and unroot them (in reverse order) just before destroy context.
 892    // For other cases use reserved slots
 893    function NewRootedValue(val: jsval): PJSRootedValue; {$ifdef HASINLINE}inline;{$endif}
 894    procedure FreeRootedValue(str: PJSRootedValue);{$ifdef HASINLINE}inline;{$endif}
 895
 896    /// Create/Free rooted object(put object in rooting stack)
 897    // Garbage collection not performs to rooted objects
 898    // - Warning!!! You must free rooted objects in reverse order for creating
 899    // that's why it's a bad idea store rooting objects in any place except
 900    // local variables. Exception is root some objects just after creating context
 901    // and unroot them (in reverse order) just before destroy context.
 902    // For other cases use reserved slots
 903    function NewRootedObject(obj: PJSObject): PJSRootedObject; {$ifdef HASINLINE}inline;{$endif}
 904    procedure FreeRootedObject(obj: PJSRootedObject);{$ifdef HASINLINE}inline;{$endif}
 905
 906    /// Create/Free rooted string(put string in rooting stack)
 907    // Garbage collection not performs to rooted strings
 908    // - Warning!!! You must free rooted strings in reverse order for creating
 909    // that's why it's a bad idea store rooting strings in any place except
 910    // local variables. Exception is root some strings just after creating context
 911    // and unroot them (in reverse order) just before destroy context.
 912    // For other cases use reserved slots
 913    function NewRootedString(obj: PJSString): PJSRootedString; {$ifdef HASINLINE}inline;{$endif}
 914    procedure FreeRootedString(str: PJSRootedString);{$ifdef HASINLINE}inline;{$endif}
 915
 916    /// create a new JavaScript string instance
 917    function NewJSString(const Value: SynUnicode): PJSString; overload; {$ifdef HASINLINE}inline;{$endif}
 918    /// create a new JavaScript string from a RawUTF8
 919    // see https://gitlab.gnome.org/GNOME/gjs/commit/6fa31261e1131970f68aba63d977253118a5958a
 920    function NewJSString(const Value: RawUTF8): PJSString; overload; {$ifdef HASINLINE}inline;{$endif}
 921    function NewJSString(TextWide: PWideChar; TextLen: integer): PJSString; overload; {$ifdef HASINLINE}inline;{$endif}
 922    function NewJSString(TextAnsi: PAnsiChar; TextLen, CodePage: integer): PJSString; overload;
 923    function NewExternalString(const Value: SynUnicode): PJSString; {$ifdef HASINLINE}inline;{$endif}
 924    //function AtomizeAndPinString(const Value: SynUnicode): PJSString; {$ifdef HASINLINE}inline;{$endif}
 925
 926    /// create a new JavaScript Date object instance
 927    function NewDateObject(year, mon, mday, hour, min, sec: int32): PJSObject; {$ifdef HASINLINE}inline;{$endif}
 928    function NewDateObjectMsec(msec: double): PJSObject; {$ifdef HASINLINE}inline;{$endif}
 929
 930    /// create a new JavaScript Array object instance
 931    function NewArrayObject(length: size_t): PJSObject; overload; {$ifdef HASINLINE}inline;{$endif}
 932    function NewArrayObject(length: size_t; vector: PjsvalVector): PJSObject; overload; {$ifdef HASINLINE}inline;{$endif}
 933
 934    /// create a new JavaScript Function object instance
 935    function NewFunction(call: JSNative; nargs: uintN; flags: uintN; name: PCChar): PJSObject; {$ifdef HASINLINE}inline;{$endif}
 936
 937    /// Reports a memory allocation error
 938    // - Call JS_ReportOutOfMemory to report that an operation failed because the
 939    // system is out of memory
 940    // - When the JavaScript engine tries to allocate memory and allocation fails,
 941    // it reports an error as though by calling this function
 942    procedure ReportOutOfMemory;
 943    /// Create a new JavaScript Error object and set it to be the pending exception on cx.
 944    // The callback must then return JS_FALSE to cause the exception to be propagated
 945    // to the calling script.
 946    procedure ReportError(format: PCChar);
 947    /// Report an error with an application-defined error code.
 948    // - varargs is Additional arguments for the error message.
 949    //- These arguments must be of type jschar*
 950    // - The number of additional arguments required depends on the error
 951    // message, which is determined by the errorCallback
 952    procedure ReportErrorNumberUC(errorCallback: JSErrorCallback; userRef: pointer; const erroNubmer: uintN);
 953    /// Offer the JavaScript engine an opportunity to perform garbage collection if needed.
 954    procedure MaybeGC;
 955
 956    /// Get the current pending exception for a given JSContext.
 957    function GetPendingException(out rv: jsval): boolean; {$ifdef HASINLINE}inline;{$endif}
 958    /// Clear the currently pending exception in a context.
 959    procedure ClearPendingException; {$ifdef HASINLINE}inline;{$endif}
 960
 961    /// Convert a jsid to type JS::Value.
 962    function IdToValue(id: jsid; out v: jsval): Boolean; //~~~ write delphi realization
 963    /// Convert a JS::Value to type jsid.
 964    function ValueToId(var v: jsval; out id: jsid): Boolean; //~~~ write delphi realization
 965
 966    /// Determines the JS data type of a JS value.
 967    function TypeOfValue(v: jsval): JSType; {$ifdef HASINLINE}inline;{$endif} //~~~ write delphi realization
 968
 969    /// Compile and execute a script in the scope of the current global of cx.
 970    function EvaluateScript(opts: PJSCompileOptions;
 971       bytes: PCChar; length: size_t;
 972       out rval: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
 973    function EvaluateUCScript(opts: PJSCompileOptions;
 974       chars: PCChar16; length: size_t;
 975       out rval: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
 976
 977    /// Compile a script, source, for execution.
 978    function CompileScript(bytes: PCChar; length: size_t; opts: PJSCompileOptions;
 979      out script: PJSScript): boolean; {$ifdef HASINLINE}inline;{$endif}
 980    function CompileUCScript(chars: PCChar16; length: size_t; opts: PJSCompileOptions;
 981      out script: PJSScript): boolean; {$ifdef HASINLINE}inline;{$endif}
 982
 983    /// Evaluate a script in the scope of the current global of cx.
 984    function ExecuteScript(var script: PJSScript; out rval: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
 985
 986    /// Return the global object for the active function on the context.
 987    // The global object is specific for a compartment
 988    function CurrentGlobalOrNull: PJSObject; {$ifdef HASINLINE}inline;{$endif}
 989
 990    //ArrayBuffer support
 991
 992    /// Create a new signed 8 bit integer typed array with nelements elements
 993    // - will fill the newly created array with zeros
 994    function NewInt8Array(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
 995
 996    /// Create a new unsigned 8 bit integer (byte) typed array with nelements elements
 997    // - will fill the newly created array with zeros
 998    function NewUint8Array(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
 999
1000    /// Create a new 8 bit integer typed array with nelements elements
1001    // - will fill the newly created array with zeros
1002    function NewUint8ClampedArray(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1003
1004    /// Create a new signed 16 bit integer typed array with nelements elements
1005    // - will fill the newly created array with zeros
1006    function NewInt16Array(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1007
1008    /// Create a new unsigned 16 bit integer typed array with nelements elements
1009    // - will fill the newly created array with zeros
1010    function NewUint16Array(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1011
1012    /// Create a new signed 32 bit integer typed array with nelements elements
1013    // - will fill the newly created array with zeros
1014    function NewInt32Array(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1015
1016    /// Create a new unsigned 32 bit integer typed array with nelements elements
1017    // - will fill the newly created array with zeros
1018    function NewUint32Array(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1019
1020    /// Create a new signed 32 bit float (single) typed array with nelements elements
1021    // - will fill the newly created array with zeros
1022    function NewFloat32Array(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1023
1024    /// Create a new signed 64 bit float (double) typed array with nelements elements
1025    // - will fill the newly created array with zeros
1026    function NewFloat64Array(nelements: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1027
1028    /// Create a new 8 bit signed integer typed array and copy in values
1029    // from a given object
1030    // - The object is used as if it was an array; that is, the new array (if
1031    // successfully created) will have length given by array.length, and its
1032    // elements will be those specified by array[0], array[1], and so on, after
1033    // conversion to the typed array element type.
1034    function NewInt8ArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1035
1036    /// Create a new 8 bit unsigned integer typed array and copy in values
1037    // from a given object
1038    // - The object is used as if it was an array; that is, the new array (if
1039    // successfully created) will have length given by array.length, and its
1040    // elements will be those specified by array[0], array[1], and so on, after
1041    // conversion to the typed array element type.
1042    function NewUint8ArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1043
1044    /// Create a new 8 bit unsigned integer typed array and copy in values
1045    // from a given object
1046    // - The object is used as if it was an array; that is, the new array (if
1047    // successfully created) will have length given by array.length, and its
1048    // elements will be those specified by array[0], array[1], and so on, after
1049    // conversion to the typed array element type.
1050    function NewUint8ClampedArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1051
1052    /// Create a new 16 bit signed integer typed array and copy in values
1053    // from a given object
1054    // - The object is used as if it was an array; that is, the new array (if
1055    // successfully created) will have length given by array.length, and its
1056    // elements will be those specified by array[0], array[1], and so on, after
1057    // conversion to the typed array element type.
1058    function NewInt16ArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1059
1060    /// Create a new 16 bit unsigned integer typed array and copy in values
1061    // from a given object
1062    // - The object is used as if it was an array; that is, the new array (if
1063    // successfully created) will have length given by array.length, and its
1064    // elements will be those specified by array[0], array[1], and so on, after
1065    // conversion to the typed array element type.
1066    function NewUint16ArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1067
1068    /// Create a new 32 bit signed integer typed array and copy in values
1069    // from a given object
1070    // - The object is used as if it was an array; that is, the new array (if
1071    // successfully created) will have length given by array.length, and its
1072    // elements will be those specified by array[0], array[1], and so on, after
1073    // conversion to the typed array element type.
1074    function NewInt32ArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1075
1076    /// Create a new 32 bit unsigned integer typed array and copy in values
1077    // from a given object
1078    // - The object is used as if it was an array; that is, the new array (if
1079    // successfully created) will have length given by array.length, and its
1080    // elements will be those specified by array[0], array[1], and so on, after
1081    // conversion to the typed array element type.
1082    function NewUint32ArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1083
1084    /// Create a new 32 bit float (single) typed array and copy in values
1085    // from a given object
1086    // - The object is used as if it was an array; that is, the new array (if
1087    // successfully created) will have length given by array.length, and its
1088    // elements will be those specified by array[0], array[1], and so on, after
1089    // conversion to the typed array element type.
1090    function NewFloat32ArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1091
1092    /// Create a new 64 bit float (double) typed array and copy in values
1093    // from a given object
1094    // - The object is used as if it was an array; that is, the new array (if
1095    // successfully created) will have length given by array.length, and its
1096    // elements will be those specified by array[0], array[1], and so on, after
1097    // conversion to the typed array element type.
1098    function NewFloat64ArrayFromArray(var arr: PJSObject): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1099
1100    /// Create a new 8 bit signed integer typed array using the given
1101    // ArrayBuffer for storage
1102    // - The length value is optional; if -1 is passed, enough elements to use up the
1103    // remainder of the byte array is used as the default value
1104    function NewInt8ArrayWithBuffer(var arrayBuffer: PJSObject;
1105      byteOffset: uint32; length: int32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1106
1107    /// Create a new 8 bit unsigned integer typed array using the given
1108    // ArrayBuffer for storage
1109    // - The length value is optional; if -1 is passed, enough elements to use up the
1110    // remainder of the byte array is used as the default value
1111    function NewUint8ArrayWithBuffer(var arrayBuffer: PJSObject;
1112      byteOffset: uint32; length: int32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1113
1114    /// Create a new 8 bit unsigned integer typed array using the given
1115    // ArrayBuffer for storage
1116    // - The length value is optional; if -1 is passed, enough elements to use up the
1117    // remainder of the byte array is used as the default value
1118    function NewUint8ClampedArrayWithBuffer(var arrayBuffer: PJSObject;
1119      byteOffset: uint32; length: int32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1120
1121    /// Create a new 16 bit signed integer typed array using the given
1122    // ArrayBuffer for storage
1123    // - The length value is optional; if -1 is passed, enough elements to use up the
1124    // remainder of the byte array is used as the default value
1125    function NewInt16ArrayWithBuffer(var arrayBuffer: PJSObject;
1126     byteOffset: uint32; length: int32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1127
1128    /// Create a new 16 bit unsigned integer typed array using the given
1129    // ArrayBuffer for storage
1130    // - The length value is optional; if -1 is passed, enough elements to use up the
1131    // remainder of the byte array is used as the default value
1132    function NewUint16ArrayWithBuffer(var arrayBuffer: PJSObject;
1133     byteOffset: uint32; length: int32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1134
1135    /// Create a new 32 bit signed integer typed array using the given
1136    // ArrayBuffer for storage
1137    // - The length value is optional; if -1 is passed, enough elements to use up the
1138    // remainder of the byte array is used as the default value
1139    function NewInt32ArrayWithBuffer(var arrayBuffer: PJSObject;
1140     byteOffset: uint32; length: int32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1141
1142    /// Create a new 32 bit unsigned integer typed array using the given
1143    // ArrayBuffer for storage
1144    // - The length value is optional; if -1 is passed, enough elements to use up the
1145    // remainder of the byte array is used as the default value
1146    function NewUint32ArrayWithBuffer(var arrayBuffer: PJSObject;
1147     byteOffset: uint32; length: int32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1148
1149    /// Create a new 32 bit float (single) typed array using the given
1150    // ArrayBuffer for storage
1151    // - The length value is optional; if -1 is passed, enough elements to use up the
1152    // remainder of the byte array is used as the default value
1153    function NewFloat32ArrayWithBuffer(var arrayBuffer: PJSObject;
1154     byteOffset: uint32; length: int32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1155
1156    /// Create a new 64 bit float (double) typed array using the given
1157    // ArrayBuffer for storage
1158    // - The length value is optional; if -1 is passed, enough elements to use up the
1159    // remainder of the byte array is used as the default value
1160    function NewFloat64ArrayWithBuffer(var arrayBuffer: PJSObject;
1161     byteOffset: uint32; length: int32): PJSObject; {$ifdef HASINLINE}inline;{$endif}
1162
1163    /// Create a new SharedArrayBuffer with the given byte length.
1164    function NewSharedArrayBuffer(nbytes: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1165
1166    /// Create a new ArrayBuffer with the given byte length.
1167    function NewArrayBuffer(nbytes: uint32): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1168
1169    /// Indicates whether or not a script or function is currently executing in a given context.
1170    property IsRunning: boolean read GetIsRunning;
1171    /// Destroy a JSContext.
1172    procedure Destroy;
1173  end;
1174
1175  /// JavaScript execution compartment
1176  // - this object does not store anything, but just provide some helper methods
1177  JSCompartment = object
1178  end;
1179  /// options of compartment
1180  JS_CompartmentOptions = record
1181    version: JSVersion;
1182    invisibleToDebugger: Boolean;
1183    mergeable: Boolean;
1184    discardSource: Boolean;
1185    disableLazyParsing_: Boolean;
1186    cloneSingletons: Boolean;
1187    extraWarningsOverride: JSUnknown;
1188    zone_: JSUnknown;
1189    traceGlobal: JSTraceOp;
1190    singletonsAsTemplates: Boolean;
1191    addonId: JSUnknown;
1192    preserveJitCode: Boolean;
1193  end;
1194
1195  /// JSObject is the type of JavaScript objects in the JSAPI
1196  // - this object does not store anything, but just provide some helper methods
1197  // to access a PJSObject value via low-level API functions
1198  {$ifdef USERECORDWITHMETHODS}JSObject = record
1199    {$else}JSObject = object{$endif}
1200  private
1201    function GetPrivate: Pointer; {$ifdef HASINLINE}inline;{$endif}
1202    procedure SetPrivate(data: Pointer); cdecl; {$ifdef HASINLINE}inline;{$endif}
1203    function GetReservedSlot(index: uint32): jsval; {$ifdef HASINLINE}inline;{$endif}
1204    procedure SetReservedSlot(index: uint32; v: jsval); {$ifdef HASINLINE}inline;{$endif}
1205    function GetClass: PJSClass; {$ifdef HASINLINE}inline;{$endif}
1206    function GetConstructor(cx: PJSContext): PJSObject; {$ifdef HASINLINE}inline;{$endif}
1207    // Return the available byte length of an array buffer
1208    // - obj must have passed a JS_IsArrayBufferObject test, or somehow be known
1209    // that it would pass such a test: it is an ArrayBuffer or a wrapper of an
1210    // ArrayBuffer, and the unwrapping will succeed
1211    function GetArrayBufferByteLength: uint32;{$ifdef HASINLINE}inline;{$endif}
1212    function GetSharedArrayBufferByteLength: uint32;{$ifdef HASINLINE}inline;{$endif}
1213    // Return a pointer to the start of the data referenced by any typed array
1214    // - The data is still owned by the typed array, and should not be modified on
1215    // another thread
1216    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1217    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1218    // unwrapping will succeed
1219    // - Prefer the type-specific versions when possible
1220    function GetArrayBufferViewData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pointer;{$ifdef HASINLINE}inline;{$endif}
1221  public
1222    /// get a jsval corresponding to this object
1223    function ToJSValue: jsval; {$ifdef HASINLINE}inline;{$endif}
1224
1225    /// Access the private data field of an object.
1226    property PrivateData: Pointer read GetPrivate write SetPrivate;
1227
1228    property Ctor[cx: PJSContext]: PJSObject read GetConstructor;
1229    /// Read access an object's reserved slots.
1230    property ReservedSlot[index: uint32]: jsval read GetReservedSlot write SetReservedSlot;
1231    /// Retrieves the class associated with an object.
1232    property Class_: PJSClass read GetClass;
1233
1234    /// JSAPI method equivalent to the instanceof operator in JavaScript.
1235    function HasInstance(cx: PJSContext; var val: jsval): Boolean;
1236
1237    /// is object is Date object
1238    function isDate(cx: PJSContext): Boolean; {$ifdef HASINLINE}inline;{$endif}
1239    /// is object is Function object
1240    function isFunction(cx: PJSContext): Boolean; {$ifdef HASINLINE}inline;{$endif}
1241    /// is object is Array object
1242    function isArray(cx: PJSContext): Boolean; {$ifdef HASINLINE}inline;{$endif}
1243
1244    /// Retrieve the private data associated with an object, if that object is an
1245    // instance of a specified class.
1246    function GetInstancePrivate(cx: PJSContext; clasp: PJSClass): Pointer; {$ifdef HASINLINE}inline;{$endif}
1247
1248    /// Create a new property on an object.
1249    function DefineProperty(cx: PJSContext; const name: PCChar;
1250        const value: jsval; attrs: uint32 = 0;
1251        getter: JSNative = nil; setter: JSNative = nil): boolean; {$ifdef HASINLINE}inline;{$endif}
1252    function DefineUCProperty(cx: PJSContext; const name: SynUnicode;
1253        const value: jsval; attrs: uint32 = 0;
1254        getter: JSNative = nil; setter: JSNative = nil): Boolean; overload; {$ifdef HASINLINE}inline;{$endif}
1255    function DefineUCProperty(cx: PJSContext; const name: PCChar16; namelen: size_t;
1256        const value: jsval; attrs: uint32 = 0;
1257        getter: JSNative = nil; setter: JSNative = nil): Boolean; overload; {$ifdef HASINLINE}inline;{$endif}
1258    function DefinePropertyById(cx: PJSContext; var id: jsid;
1259        const value: jsval; attrs: uint32 = 0;
1260        getter: JSNative = nil; setter: JSNative = nil): boolean; {$ifdef HASINLINE}inline;{$endif}
1261    /// Define multiple properties for a single object.
1262    // PJSPropertySpec must be null-terminated
1263    function DefineProperties(cx: PJSContext; ps: PJSPropertySpec): boolean; {$ifdef HASINLINE}inline;{$endif}
1264
1265    /// Find a specified property and retrieve its value.
1266    function GetPropValue(cx: PJSContext; const name: SynUnicode): jsval;{$ifdef HASINLINE}inline;{$endif}
1267    function GetProperty(cx: PJSContext; const name: PCChar; out vp: jsval): boolean; {$ifdef HASINLINE}inline;{$endif}
1268    function GetUCProperty(cx: PJSContext; const name: PCChar16; namelen: size_t; out vp: jsval): boolean; {$ifdef HASINLINE}inline;{$endif}
1269    function GetPropertyById(cx: PJSContext; const id: jsid; out vp: jsval): boolean; {$ifdef HASINLINE}inline;{$endif}
1270
1271    /// Assign a value to a property of an object.
1272    function SetProperty(cx: PJSContext; const name: PCChar; const vp: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
1273    function SetUCProperty(cx: PJSContext; const name: PCChar16; namelen: size_t; const vp: jsval): boolean; {$ifdef HASINLINE}inline;{$endif}
1274
1275    /// Removes a specified property from an object.
1276    function DeletePropertyById(cx: PJSContext; const id: jsid;
1277      out res: JS_ObjectOpResult): Boolean; {$ifdef HASINLINE}inline;{$endif}
1278
1279    /// Determine whether a JavaScript object has a specified property.
1280    function HasProperty(cx: PJSContext; const name: PCChar): Boolean; {$ifdef HASINLINE}inline;{$endif}
1281    function HasUCProperty(cx: PJSContext; const name: PCChar16; namelen: size_t; out found: Boolean): Boolean; {$ifdef HASINLINE}inline;{$endif}
1282
1283    /// Determine whether a property is already physically present on a JSObject.
1284    function AlreadyHasOwnUCProperty(cx: PJSContext; const name: PCChar16; namelen: size_t): Boolean; {$ifdef HASINLINE}inline;{$endif}
1285
1286    /// Create a native function and assign it as a property to a specified JS object
1287    function DefineFunction(cx: PJSContext; name: PCChar;
1288        call: JSNative; nargs: uintN; attrs: uintN = 0): PJSFunction; {$ifdef HASINLINE}inline;{$endif}
1289    function DefineUCFunction(cx: PJSContext; name: PCChar16;
1290        namelen: size_t; call: JSNative; nargs: uintN; attrs: uintN = 0): PJSFunction; {$ifdef HASINLINE}inline;{$endif}
1291
1292    /// Create zero or more functions and makes them properties (methods)
1293    // of a specified object, obj, as if by calling JS_DefineFunction repeatedly
1294    function DefineFunctions(cx: PJSContext; fs: PJSFunctionSpec;
1295        behavior: JSPropertyDefinitionBehavior = DefineAllProperties): Boolean; {$ifdef HASINLINE}inline;{$endif}
1296
1297    /// Calls a specified JS function.
1298    // - Perform the method call `rval = obj[name](args)`.
1299    function RunMethod(cx: PJSContext; const name: PCChar;
1300      args: TjsvalDynArray; out rval: jsval): Boolean; overload; {$ifdef HASINLINE}inline;{$endif}
1301    function RunMethod(cx: PJSContext; const name: PCChar;
1302      arg: jsval; out rval: jsval): Boolean; overload; {$ifdef HASINLINE}inline;{$endif}
1303    function RunMethod(cx: PJSContext; const name: PCChar;
1304      out rval: jsval): Boolean; overload; {$ifdef HASINLINE}inline;{$endif}
1305    function CallFunction(cx: PJSContext; var fun: PJSFunction;
1306      argc: size_t; argv: PjsvalVector; out rval: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
1307    function CallFunctionValue(cx: PJSContext; val: jsval;
1308      argc: size_t; argv: PjsvalVector; out rval: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
1309    function CallFunctionName(cx: PJSContext; const name: PCChar;
1310      argc: size_t; argv: PjsvalVector; out rval: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
1311
1312    /// Make a JSClass accessible to JavaScript code by creating its prototype,
1313    // constructor, properties, and functions.
1314    function InitClass(cx: PJSContext; var parent_proto: PJSObject;
1315      clasp: PJSClass; _constructor: JSNative; nargs: Cardinal;
1316      ps: PJSPropertySpec; fs: PJSFunctionSpec;
1317      static_ps: PJSPropertySpec; static_fs: PJSFunctionSpec): PJSObject; {$ifdef HASINLINE}inline;{$endif}
1318
1319    /// Get the prototype of obj, storing it in result.
1320    // - Implements: ES6 [[GetPrototypeOf]] internal method.
1321    function GetPrototype(cx: PJSContext; out protop: PJSObject): Boolean; {$ifdef HASINLINE}inline;{$endif}
1322    /// Change the prototype of obj.
1323    // - Implements: ES6 [[SetPrototypeOf]] internal method.
1324    // - In cases where ES6 [[SetPrototypeOf]] returns false without an exception,
1325    // JS_SetPrototype throws a TypeError and returns false.
1326    // - Performance warning: JS_SetPrototype is very bad for performance. It may
1327    // cause compiled jit-code to be invalidated. It also causes not only obj but
1328    // all other objects in the same "group" as obj to be permanently deoptimized.
1329    // It's better to create the object with the right prototype from the start.
1330    function SetPrototype(cx: PJSContext; var proto: PJSObject): Boolean; {$ifdef HASINLINE}inline;{$endif}
1331
1332    /// Get an array of the non-symbol enumerable properties of obj.
1333    // This function is roughly equivalent to:
1334    //
1335    //     var result = [];
1336    //     for (key in obj)
1337    //         result.push(key);
1338    //     return result;
1339    //
1340    // This is the closest thing we currently have to the ES6 [[Enumerate]]
1341    // internal method.
1342    function Enumerate(cx: PJSContext; out length: size_t;
1343      out data: PjsidVector): PJSIdArray;
1344
1345    //array methods
1346    function GetArrayLength(cx: PJSContext; out length: uint32): Boolean; {$ifdef HASINLINE}inline;{$endif}
1347    function GetElement(cx: PJSContext; index: uint32; out vp: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
1348    function SetElement(cx: PJSContext; index: uint32; const vp: jsval): Boolean; {$ifdef HASINLINE}inline;{$endif}
1349    function DeleteElement(cx: PJSContext; index: uint32; out res: JS_ObjectOpResult): Boolean; {$ifdef HASINLINE}inline;{$endif}
1350
1351    //function methods
1352    function GetFunctionId: PJSString; {$ifdef HASINLINE}inline;{$endif}
1353    property FunctionId: PJSString read GetFunctionId;
1354    function DecompileFunction(cx: PJSContext; PrettyPrint: Boolean = true): PJSString;
1355
1356    //arrayBuffer methods
1357
1358    /// Check whether obj supports JS_GetTypedArray* APIs
1359    // - Note that this may return false if a security wrapper is encountered that
1360    // denies the unwrapping.
1361    // - if this test or one of the JS_Is*Array tests succeeds, then it is safe to call
1362    // the dedicated accessor JSAPI calls
1363    function IsTypedArrayObject: Boolean;{$ifdef HASINLINE}inline;{$endif}
1364
1365    /// Check whether obj supports JS_GetArrayBufferView* APIs
1366    // - Note that this may return false if a security wrapper is encountered that
1367    // denies the unwrapping.
1368    // - if this test or one of the JS_Is*Array tests succeeds, then it is safe to call
1369    // the dedicated ArrayBufferView accessor JSAPI calls
1370    function IsArrayBufferViewObject: Boolean;{$ifdef HASINLINE}inline;{$endif}
1371
1372    /// Test for specific 8 bit signed integer typed array types (ArrayBufferView subtypes)
1373    function IsInt8Array: Boolean;{$ifdef HASINLINE}inline;{$endif}
1374
1375    /// Test for specific 8 bit unsigned integer typed array types (ArrayBufferView subtypes)
1376    function IsUint8Array: Boolean;{$ifdef HASINLINE}inline;{$endif}
1377
1378    /// Test for specific 8 bit unsigned integer typed array types (ArrayBufferView subtypes)
1379    function IsUint8ClampedArray: Boolean;{$ifdef HASINLINE}inline;{$endif}
1380
1381    /// Test for specific 16 bit signed integer typed array types (ArrayBufferView subtypes)
1382    function IsInt16Array: Boolean;{$ifdef HASINLINE}inline;{$endif}
1383
1384    /// Test for specific 16 bit unsigned integer typed array types (ArrayBufferView subtypes)
1385    function IsUint16Array: Boolean;{$ifdef HASINLINE}inline;{$endif}
1386
1387    /// Test for specific 32 bit signed integer typed array types (ArrayBufferView subtypes)
1388    function IsInt32Array: Boolean;{$ifdef HASINLINE}inline;{$endif}
1389
1390    /// Test for specific 32 bit unsigned integer typed array types (ArrayBufferView subtypes)
1391    function IsUint32Array: Boolean;{$ifdef HASINLINE}inline;{$endif}
1392
1393    /// Test for specific 32 bit float (single) typed array types (ArrayBufferView subtypes)
1394    function IsFloat32Array: Boolean;{$ifdef HASINLINE}inline;{$endif}
1395
1396    /// Test for specific 64 bit float (double) typed array types (ArrayBufferView subtypes)
1397    function IsFloat64Array: Boolean;{$ifdef HASINLINE}inline;{$endif}
1398
1399    /// Return the isShared flag of a typed array, which denotes whether
1400    // the underlying buffer is a SharedArrayBuffer.
1401    //
1402    // |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
1403    // be known that it would pass such a test: it is a typed array or a wrapper of
1404    // a typed array, and the unwrapping will succeed.
1405    function GetTypedArraySharedness: Boolean;{$ifdef HASINLINE}inline;{$endif}
1406
1407    /// Unwrap 8 bit signed integer typed array into direct memory buffer
1408    // - Return nil without throwing any exception if the object cannot be viewed as the
1409    // correct typed array, or the typed array object on success, filling both out parameters
1410    function GetObjectAsInt8Array(out length: uint32; out isSharedMemory:Boolean; out Data: Pint8Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1411
1412    /// Unwrap 8 bit unsigned integer typed array into direct memory buffer
1413    // - Return nil without throwing any exception if the object cannot be viewed as the
1414    // correct typed array, or the typed array object on success, filling both out parameters
1415    function GetObjectAsUint8Array(out length: uint32; out isSharedMemory:Boolean; out  Data: Puint8Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1416
1417    /// Unwrap 8 bit unsigned integer typed array into direct memory buffer
1418    // - Return nil without throwing any exception if the object cannot be viewed as the
1419    // correct typed array, or the typed array object on success, filling both out parameters
1420    function GetObjectAsUint8ClampedArray(out length: uint32; out isSharedMemory:Boolean; out  Data: Puint8Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1421
1422    /// Unwrap 16 bit signed integer typed array into direct memory buffer
1423    // - Return nil without throwing any exception if the object cannot be viewed as the
1424    // correct typed array, or the typed array object on success, filling both out parameters
1425    function GetObjectAsInt16Array(out length: uint32; out isSharedMemory:Boolean; out  Data: Pint16Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1426
1427    /// Unwrap 16 bit unsigned integer typed array into direct memory buffer
1428    // - Return nil without throwing any exception if the object cannot be viewed as the
1429    // correct typed array, or the typed array object on success, filling both out parameters
1430    function GetObjectAsUint16Array(out length: uint32; out isSharedMemory:Boolean; out  Data: Puint16Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1431
1432    /// Unwrap 32 bit signed integer typed array into direct memory buffer
1433    // - Return nil without throwing any exception if the object cannot be viewed as the
1434    // correct typed array, or the typed array object on success, filling both out parameters
1435    function GetObjectAsInt32Array(out length: uint32; out isSharedMemory:Boolean; out  Data: Pint32Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1436
1437    /// Unwrap 32 bit unsigned integer typed array into direct memory buffer
1438    // - Return nil without throwing any exception if the object cannot be viewed as the
1439    // correct typed array, or the typed array object on success, filling both out parameters
1440    function GetObjectAsUint32Array(out length: uint32; out isSharedMemory:Boolean; out  Data: Puint32Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1441
1442    /// Unwrap 32 bit float (single) typed array into direct memory buffer
1443    // - Return nil without throwing any exception if the object cannot be viewed as the
1444    // correct typed array, or the typed array object on success, filling both out parameters
1445    function GetObjectAsFloat32Array(out length: uint32; out isSharedMemory:Boolean; out  Data: Pfloat32Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1446
1447    /// Unwrap 64 bit float (double) typed array into direct memory buffer
1448    // - Return nil without throwing any exception if the object cannot be viewed as the
1449    // correct typed array, or the typed array object on success, filling both out parameters
1450    function GetObjectAsFloat64Array(out length: uint32; out isSharedMemory:Boolean; out  Data: Pfloat64Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1451
1452    /// Unwrap an object as its raw binary memory buffer
1453    // - Return nil without throwing any exception if the object cannot be viewed as the
1454    // correct typed array, or the typed array object on success, filling both out parameters
1455    function GetObjectAsArrayBufferView(out length: uint32; out isSharedMemory:Boolean; out  Data: Puint8Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1456
1457    /// Unwrap an object as its raw binary memory buffer
1458    // - Return nil without throwing any exception if the object cannot be viewed as the
1459    // correct typed array, or the typed array object on success, filling both out parameters
1460    function GetObjectAsArrayBuffer(out length: uint32; out Data: Puint8Vector): PJSObject;{$ifdef HASINLINE}inline;{$endif}
1461
1462    /// Get the type of elements in a typed array, or jsabTYPE_DATAVIEW if a DataView
1463    function GetArrayBufferViewType: JSArrayBufferViewType;{$ifdef HASINLINE}inline;{$endif}
1464
1465//    function GetSharedArrayBufferViewType: JSArrayBufferViewType;{$ifdef HASINLINE}inline;{$endif}
1466
1467    /// Check whether obj supports the JS_GetArrayBuffer* APIs
1468    // - Note that this may return false if a security wrapper is encountered that denies the
1469    // unwrapping
1470    // - If this test succeeds, then it is safe to call the various accessor JSAPI calls
1471    function IsArrayBufferObject: Boolean;{$ifdef HASINLINE}inline;{$endif}
1472
1473    function IsSharedArrayBufferObject: Boolean;
1474
1475    /// Return true if the arrayBuffer contains any data. This will return false for
1476    // ArrayBuffer.prototype and neutered ArrayBuffers.
1477    //
1478    // |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
1479    // that it would pass such a test: it is an ArrayBuffer or a wrapper of an
1480    // ArrayBuffer, and the unwrapping will succeed.
1481    function ArrayBufferHasData: Boolean;
1482
1483    /// Return a pointer to an array buffer's data
1484    // - The buffer is still owned by the array buffer object, and should not
1485    // be modified on another thread. The returned pointer is stable across GCs
1486    // - obj must have passed a JS_IsArrayBufferObject test, or somehow be known
1487    // that it would pass such a test: it is an ArrayBuffer or a wrapper of an
1488    // ArrayBuffer, and the unwrapping will succeed.
1489    function GetArrayBufferData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint8Vector; overload;{$ifdef HASINLINE}inline;{$endif}
1490    function GetArrayBufferData: Puint8Vector; overload;{$ifdef HASINLINE}inline;{$endif}
1491
1492    /// Check whether the obj is ArrayBufferObject and memory mapped. Note that this
1493    // may return false if a security wrapper is encountered that denies the
1494    // unwrapping.
1495    function IsMappedArrayBufferObject(obj: PJSObject): Boolean;{$ifdef HASINLINE}inline;{$endif}
1496
1497    /// Return the number of elements in a typed array
1498    // - obj must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
1499    // be known that it would pass such a test: it is a typed array or a wrapper of
1500    // a typed array, and the unwrapping will succeed.
1501    function GetTypedArrayLength: uint32;{$ifdef HASINLINE}inline;{$endif}
1502
1503    /// Return the byte offset from the start of an array buffer to the start of a
1504    // typed array view
1505    // - obj must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
1506    // be known that it would pass such a test: it is a typed array or a wrapper of
1507    // a typed array, and the unwrapping will succeed.
1508    function GetTypedArrayByteOffset: uint32;
1509
1510    /// Return the byte length of a typed array
1511    // - obj must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
1512    // be known that it would pass such a test: it is a typed array or a wrapper of
1513    // a typed array, and the unwrapping will succeed
1514    function GetTypedArrayByteLength: uint32;{$ifdef HASINLINE}inline;{$endif}
1515
1516    /// More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
1517    function GetArrayBufferViewByteLength: uint32;{$ifdef HASINLINE}inline;{$endif}
1518
1519    /// Return a pointer to the start of the data referenced by a typed 8 bit signed integer array
1520    // - The data is still owned by the typed array, and should not be modified on
1521    // another thread
1522    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1523    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1524    // unwrapping will succeed
1525    function GetInt8ArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pint8Vector;{$ifdef HASINLINE}inline;{$endif}
1526
1527    /// Return a pointer to the start of the data referenced by a typed 8 bit unsigned integer array
1528    // - The data is still owned by the typed array, and should not be modified on
1529    // another thread
1530    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1531    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1532    // unwrapping will succeed
1533    function GetUint8ArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint8Vector; overload;{$ifdef HASINLINE}inline;{$endif}
1534    function GetUInt8ArrayData: Puint8Vector; overload;{$ifdef HASINLINE}inline;{$endif}
1535
1536    /// Return a pointer to the start of the data referenced by a typed 8 bit unsigned integer array
1537    // - The data is still owned by the typed array, and should not be modified on
1538    // another thread
1539    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1540    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1541    // unwrapping will succeed
1542    function GetUint8ClampedArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint8Vector;{$ifdef HASINLINE}inline;{$endif}
1543
1544    /// Return a pointer to the start of the data referenced by a typed 16 bit signed integer array
1545    // - The data is still owned by the typed array, and should not be modified on
1546    // another thread
1547    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1548    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1549    // unwrapping will succeed
1550    function GetInt16ArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pint16Vector;{$ifdef HASINLINE}inline;{$endif}
1551
1552    /// Return a pointer to the start of the data referenced by a typed 16 bit unsigned integer array
1553    // - The data is still owned by the typed array, and should not be modified on
1554    // another thread
1555    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1556    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1557    // unwrapping will succeed
1558    function GetUint16ArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint16Vector;{$ifdef HASINLINE}inline;{$endif}
1559
1560    /// Return a pointer to the start of the data referenced by a typed 32 bit signed integer array
1561    // - The data is still owned by the typed array, and should not be modified on
1562    // another thread
1563    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1564    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1565    // unwrapping will succeed
1566    function GetInt32ArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pint32Vector;{$ifdef HASINLINE}inline;{$endif}
1567
1568    /// Return a pointer to the start of the data referenced by a typed 32 bit unsigned integer array
1569    // - The data is still owned by the typed array, and should not be modified on
1570    // another thread
1571    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1572    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1573    // unwrapping will succeed
1574    function GetUint32ArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint32Vector;{$ifdef HASINLINE}inline;{$endif}
1575
1576    /// Return a pointer to the start of the data referenced by a typed 32 bit float (single) array
1577    // - The data is still owned by the typed array, and should not be modified on
1578    // another thread
1579    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1580    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1581    // unwrapping will succeed
1582    function GetFloat32ArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pfloat32Vector;{$ifdef HASINLINE}inline;{$endif}
1583
1584    /// Return a pointer to the start of the data referenced by a typed 64 bit float (double) array
1585    // - The data is still owned by the typed array, and should not be modified on
1586    // another thread
1587    // - obj must have passed a JS_Is*Array test, or somehow be known that it would
1588    // pass such a test: it is a typed array or a wrapper of a typed array, and the
1589    // unwrapping will succeed
1590    function GetFloat64ArrayData(out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pfloat64Vector;{$ifdef HASINLINE}inline;{$endif}
1591
1592    /// Return a pointer to the start of the data referenced by any typed array
1593    // and it's length. For ArrayBufferView return a pointer and length of slice.
1594    // - The data is still owned by the typed array, and should not be modified on
1595    // another thread
1596    // - If JSObject is not a typed array or arrayBufferView return false
1597    function GetBufferDataAndLength(out data: Puint8Vector; out len: uint32): boolean;{$ifdef HASINLINE}inline;{$endif}
1598  end;
1599
1600  JSString = object
1601    /// get the UTF-8 text corresponding to this string, for a given
1602    // runtime execution context
1603    function ToUTF8(cx: PJSContext): RawUTF8; overload;
1604    /// get the UTF-8 text corresponding to this string, for a given
1605    // runtime execution context
1606    // - slightly faster overloaded method (avoid string assignment)
1607    procedure ToUTF8(cx: PJSContext; out result: RawUTF8); overload;
1608    /// Add UTF-8 text corresponding to this string to writer,
1609    // without escaping
1610    procedure ToUTF8(cx: PJSContext; W: TTextWriter); overload;
1611
1612    /// get the Ansi text corresponding to this string
1613    // if source string containt non-ascii chars
1614    // convert it to Ansi using global CurrentAnsiConvert from SynCommons
1615    function ToAnsi(cx: PJSContext): AnsiString;
1616
1617    /// get the UTF-16 text corresponding to this string, for a given
1618    // runtime execution context
1619    function ToSynUnicode(cx: PJSContext): SynUnicode;
1620    function ToString(cx: PJSContext): string;
1621    procedure ToVariant(cx: PJSContext; var Value: Variant);
1622    procedure ToJSONString(cx: PJSContext; W: TTextWriter);
1623    /// get a jsval corresponding to this string
1624    function ToJSVal: jsval;
1625
1626    function HasLatin1Chars: Boolean;
1627    function Length: size_t;
1628
1629    function GetLatin1StringCharsAndLength(cx: PJSContext; out len: size_t):PCChar;
1630    function GetTwoByteStringCharsAndLength(cx: PJSContext; out len: size_t):PCChar16;
1631  end;
1632
1633  JSClassOps = record
1634    addProperty:        JSAddPropertyOp;
1635    delProperty:        JSDeletePropertyOp;
1636    getProperty:        JSGetterOp;
1637    setProperty:        JSSetterOp;
1638    enumerate:          JSEnumerateOp;
1639    resolve:            JSResolveOp;
1640    mayResolve:         JSMayResolveOp;
1641    finalize:           JSFinalizeOp;
1642    call:               JSNative;
1643    hasInstance:        JSHasInstanceOp;
1644    construct:          JSNative;
1645    trace:              JSTraceOp;
1646  end;
1647  PJSClassOps = ^JSClassOps;
1648
1649  JSClass =  record
1650    name:               PCChar;
1651    flags:              uint32;
1652    cOps:               PJSClassOps;
1653    reserved:           array [0..2] of pointer;
1654  end;
1655
1656  { JSCompileOptions }
1657  JSCompileOptions = object
1658    procedure SetFileLineAndUtf8(const fn: RawUTF8; l: cardinal; isUtf8: boolean);
1659  end;
1660
1661  // internal alignment of JSCompileOptions is a HACK and depends on C++ pragma
1662  // the only function we need is JSCompileOptions.SetFileLineAndUtf8
1663  //JSCompileOptions = record
1664  //  reserved: array[0..1] of Pointer;
1665  //  filename: PCChar;
1666  //
1667  //  introducerFilename_: PCChar;
1668  //  sourceMapURL_: PCChar16;
1669  //  version: JSVersion; //JSVersion version;
1670  //  versionSet: boolean; //bool versionSet;
1671  //  utf8: boolean; //bool utf8
1672  //  selfHostingMode: boolean; // bool selfHostingMode
1673  //  canLazilyParse: boolean; // bool canLazilyParse
1674  //  //strictOption: boolean;
1675  //  //extraWarningsOption: boolean;
1676  //  //werrorOption: boolean;
1677  //  //AsmJSOption asmJSOption;
1678  //  //bool throwOnAsmJSValidationFailureOption;
1679  //  //bool forceAsync;
1680  //  //bool installedFile;  // 'true' iff pre-compiling js file in packaged app
1681  //  //bool sourceIsLazy;
1682  //  reserved1: array[{$ifdef CPUX64}6{$else}7{$endif}..24] of Pointer;
1683  //end;
1684
1685  JSRootedValue = record
1686    Stack: JSUnknown;
1687    prev: JSUnknown;
1688    ptr: jsval;
1689  end;
1690  JSRootedObjectStack = record
1691    Last: PJSRootedObject;
1692  end;
1693  PJSRootedObjectStack = ^JSRootedObjectStack;
1694  JSRootedObject = record
1695    Stack: PJSRootedObjectStack;
1696    prev: PJSRootedObject;
1697    ptr: PJSObject;
1698  end;
1699
1700  JSRootedString = record
1701    Stack: JSUnknown;
1702    prev: JSUnknown;
1703    ptr: PJSString;
1704  end;
1705
1706  PJSJitInfo = JSUnknown;
1707  JSNativeWrapper = record
1708    op: JSNative;
1709    info: PJSJitInfo
1710  end;
1711  SelfHostedWrapper = record
1712    unused: Pointer;
1713    funname: PCChar;
1714  end;
1715  JSPropertySpecGetSetRec = record
1716    case Boolean of
1717    true: (native: JSNativeWrapper);
1718    false: (selfHosted: SelfHostedWrapper);
1719  end;
1720  JSPropertySpec = record
1721    name: PCChar;
1722    flags: uint8;
1723    getter: JSPropertySpecGetSetRec;
1724    setter: JSPropertySpecGetSetRec;
1725  end;
1726  TJSPropertySpecDynArray = array of JSPropertySpec;
1727
1728  JSFunctionSpec = record
1729    name: PCChar;
1730    call: JSNativeWrapper;
1731    nargs: uint16;
1732    flags: uint16;
1733    selfHostedName: PCChar;
1734  end;
1735  TJSFunctionSpecArray = array of JSFunctionSpec;
1736
1737  /// internal structure used to report JavaScript errors
1738  JSErrorReport = record
1739    /// The (default) error message.
1740    // If ownsMessage is true, the it is freed in destructor.
1741    message_: PUTF8Char;
1742    /// offending source line without final #13
1743    // If ownsLinebuf is true, the buffer is freed in destructor.
1744    linebuf: PCChar16;
1745    /// number of chars in linebuf_. Does not include trailing '\0'
1746    linebufLength: size_t;
1747    /// The 0-based offset of error token in linebuf_.
1748    tokenOffset: size_t;
1749    /// source file name, URL, etc., or null
1750    filename: PCChar;
1751    /// source line number
1752    lineno: uint32;
1753    /// zero-based column index in line
1754    column: uint32;
1755    /// error/warning, etc.
1756    flags: uint32;
1757    /// the error number, e.g. see js.msg
1758    errorNumber: uint32;
1759    /// One of the JSExnType constants
1760    exnType: JSExnType;
1761    /// See the comment in ReadOnlyCompileOptions.
1762    isMuted: Boolean;
1763    ownsLinebuf: Boolean;
1764    ownsMessage: Boolean;
1765  end;
1766
1767  /// used by JSErrorCallback() callback
1768  JSErrorFormatString = record
1769    /// The error message name in ASCII.
1770    name: PCChar;
1771    /// The error format string (UTF-8 if js_CStringsAreUTF8)
1772    format: PCChar;
1773    /// The number of arguments to expand in the formatted error message
1774    argCount: uint16;
1775    /// One of the JSExnType constants above
1776    exnType: JSExnType;
1777  end;
1778
1779/// * Finalizes external strings created by JS_NewExternalString.
1780  JSStringFinalizer = record
1781    finalize: JSStringFinalizerOp;
1782  end;
1783
1784const
1785  /// JSClass instance objects have private slot
1786  JSCLASS_HAS_PRIVATE             =   1 shl 0;
1787  /// JSClass instance class's initialization code will call
1788  // SetNewObjectMetadata itself
1789  JSCLASS_DELAY_METADATA_CALLBACK =   1 shl 1;
1790  /// JSClass instance private is (nsISupports*)
1791  JSCLASS_PRIVATE_IS_NSISUPPORTS =   1 shl 3;
1792  /// JSClass instance objects are DOM
1793  JSCLASS_IS_DOMJSCLASS          =   1 shl 4;
1794  /// JSClass instance objects of this class act like the value undefined,
1795  // in some contexts
1796  JSCLASS_EMULATES_UNDEFINED     =   1 shl 6;
1797  /// Reserved for embeddings.
1798  JSCLASS_USERBIT1               =   1 shl 7;
1799  /// JSClass instance room for 8 flags below
1800  JSCLASS_RESERVED_SLOTS_SHIFT   = 8;
1801  /// JSClass instance and 16 above this field
1802  JSCLASS_RESERVED_SLOTS_WIDTH   = 8;
1803
1804  JSCLASS_RESERVED_SLOTS_MASK    = (uint32(1) shl JSCLASS_RESERVED_SLOTS_WIDTH)-1;
1805  JSCLASS_HIGH_FLAGS_SHIFT       = (JSCLASS_RESERVED_SLOTS_SHIFT + JSCLASS_RESERVED_SLOTS_WIDTH);
1806
1807  JSCLASS_IS_ANONYMOUS           = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+0));
1808  JSCLASS_IS_GLOBAL              = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+1));
1809  JSCLASS_INTERNAL_FLAG2         = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+2));
1810  JSCLASS_INTERNAL_FLAG3         = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+3));
1811
1812  JSCLASS_IS_PROXY               = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+4));
1813
1814  JSCLASS_SKIP_NURSERY_FINALIZE  = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+5));
1815  // Reserved for embeddings.
1816  JSCLASS_USERBIT2               = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+6));
1817  JSCLASS_USERBIT3               = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+7));
1818
1819  JSCLASS_BACKGROUND_FINALIZE    = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+8));
1820  JSCLASS_FOREGROUND_FINALIZE    = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+9));
1821// Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see
1822// below.
1823
1824  JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
1825
1826//  JSProto_LIMIT = 46;
1827  JSCLASS_GLOBAL_SLOT_COUNT         = (JSCLASS_GLOBAL_APPLICATION_SLOTS + ord(JSProto_LIMIT) * 2 + 39);
1828
1829  JSCLASS_GLOBAL_FLAGS              = JSCLASS_IS_GLOBAL or
1830                                      (((JSCLASS_GLOBAL_SLOT_COUNT) and JSCLASS_RESERVED_SLOTS_MASK) shl JSCLASS_RESERVED_SLOTS_SHIFT);
1831
1832
1833/// Property attributes, set in JSPropertySpec and passed to API functions.
1834// NB: The data structure in which some of these values are stored only uses
1835//     a uint8_t to store the relevant information. Proceed with caution if
1836//     trying to reorder or change the the first byte worth of flags.
1837
1838  JSPROP_ENUMERATE        = $01; // property is visible to for/in loop
1839  JSPROP_READONLY         = $02; // not settable: assignment is no-op.
1840                                  //  This flag is only valid when neither
1841                                  //  JSPROP_GETTER nor JSPROP_SETTER is
1842                                  //  set.
1843  JSPROP_PERMANENT        = $04; // property cannot be deleted
1844  JSPROP_PROPOP_ACCESSORS = $08; // Passed to JS_Define(UC)Property* and
1845                                  //  JS_DefineElement if getters/setters
1846                                  //  are JSPropertyOp/JSStrictPropertyOp
1847  JSPROP_GETTER           = $10; // property holds getter function
1848  JSPROP_SETTER           = $20; // property holds setter function
1849  JSPROP_SHARED           = $40; // don't allocate a value slot for this
1850                                  // property; don't copy the property on
1851                                  // set of the same-named property in an
1852                                  // object that delegates to a prototype
1853                                  // containing this property
1854  JSPROP_INTERNAL_USE_BIT= $80; // name is actually (int) index
1855  JSPROP_DEFINE_LATE     = $100; // Don't define property when initially creating
1856                                  // the constructor. Some objects like Function/Object
1857                                  // have self-hosted functions that can only be defined
1858                                  // after the initialization is already finished.
1859  JSFUN_STUB_GSOPS       = $200; // use JS_PropertyStub getter/setter
1860                                  // instead of defaulting to class gsops
1861                                  // for property holding function
1862
1863  JSFUN_CONSTRUCTOR      = $400; // native that can be called as a ctor
1864  /// enumerable read-only property attributes
1865  JSPROPS_STATIC_RO      = JSPROP_ENUMERATE or JSPROP_READONLY or JSPROP_PERMANENT;
1866
1867  JSFUN_HAS_REST = $1000; // function has ...rest parameter.
1868
1869  JSPROP_REDEFINE_NONCONFIGURABLE = $1000; // If set, will allow redefining a
1870                                           // non-configurable property, but
1871                                           // only on a non-DOM global.  This
1872                                           // is a temporary hack that will
1873                                           // need to go away in bug
1874                                           // 1105518
1875
1876// Resolve hooks and enumerate hooks must pass this flag when calling
1877// JS_Define* APIs to reify lazily-defined properties.
1878// JSPROP_RESOLVING is used only with property-defining APIs. It tells the
1879// engine to skip the resolve hook when performing the lookup at the beginning
1880// of property definition. This keeps the resolve hook from accidentally
1881// triggering itself: unchecked recursion.
1882// For enumerate hooks, triggering the resolve hook would be merely silly, not
1883// fatal, except in some cases involving non-configurable properties.
1884  JSPROP_RESOLVING        = $2000;
1885
1886  JSPROP_IGNORE_ENUMERATE = $4000;  // ignore the value in JSPROP_ENUMERATE.
1887                                    // This flag only valid when defining over
1888                                    // an existing property.
1889  JSPROP_IGNORE_READONLY  = $8000;  // ignore the value in JSPROP_READONLY.
1890                                    // This flag only valid when defining over
1891                                    // an existing property.
1892  JSPROP_IGNORE_PERMANENT = $10000; // ignore the value in JSPROP_PERMANENT.
1893                                    // This flag only valid when defining over
1894                                    // an existing property.
1895  JSPROP_IGNORE_VALUE     = $20000; // ignore the Value in the descriptor. Nothing was
1896                                    // specified when passed to Object.defineProperty
1897                                    // from script.
1898
1899type
1900  /// available options for JS Objects Properties
1901  TJSPropertyAttr = (
1902    jspEnumerate, jspReadOnly, jspPermanent, jspPropAccessors, jspGetter,
1903    jspSetter, jspShared, jspInternal, jspDefineLate,
1904    jspFunStubGSOps, jspFunConstructor, jspFunGenericNative,
1905    jspRedefineNonConfigurable, jspResolving,
1906    jspIgnoreEnumerate, jspIgnoreReadOnly, jspIgnorePermanent, jspIgnoreValue);
1907  /// set of available options for JS Objects Properties
1908  TJSPropertyAttrs = set of TJSPropertyAttr;
1909
1910  ESMException = class(ESynException)
1911  private
1912    FJSErrorNum: integer;
1913    FFileName: RawUTF8;
1914    FLineNum: integer;
1915    FJSStackTrace: SynUnicode;
1916  public
1917    /// constructor which will create JavaScript exception with JS stack trace
1918    constructor CreateWithTrace(const AFileName: RawUTF8; AJSErrorNum, ALineNum: integer;
1919       AMessage: string; const AStackTrace: SynUnicode);
1920    /// Format a JS exception as text
1921    // If SM_DEBUG is defined will write full JS stack, including SyNode core_modules calls
1922    //  if not - core_modules is cutched from stack trace for simplicity
1923    procedure WriteFormatted(WR: TTextWriter);
1924
1925    {$ifndef NOEXCEPTIONINTERCEPT}
1926    /// Custmize SM exception log output
1927    function CustomLog(WR: TTextWriter; const Context: TSynLogExceptionContext): boolean; override;
1928    {$endif}
1929  published
1930    property ErrorNum: integer read FJSErrorNum;
1931    property Stack: SynUnicode read FJSStackTrace;
1932    property FileName: RawUTF8 read FFileName;
1933    property Line: integer read FLineNum;
1934  end;
1935
1936/// pass exception of this type to JSError for raising JS RangeError exception
1937  ESMRangeException = class(ESMException);
1938/// pass exception of this type to JSError for raising JS TypeError exception
1939  ESMTypeException = class(ESMException);
1940
1941/// to be used to catch Delphi exceptions inside JSNative function implementation
1942// - usage example:
1943// ! try
1944// !   doSomething()
1945// !   Result := True;
1946// ! except
1947// ! on E: Exception do begin
1948// !   JSError(cx, E);
1949// !   Result := False;
1950// ! end;
1951
1952procedure JSError(cx: PJSContext; aException: Exception);
1953procedure JSErrorUC(cx: PJSContext; aMessage: WideString; errorCode: integer = 0);
1954procedure JSRangeErrorUC(cx: PJSContext; aMessage: WideString);
1955procedure JSTypeErrorUC(cx: PJSContext; aMessage: WideString);
1956
1957// must be called ONCE per process before any interaction with JavaScript
1958function InitJS: Boolean;
1959// must be called ONCE per process after all engine managers are destroyed
1960procedure ShutDownJS;
1961
1962var
1963    nullObj: PJSObject = nil;
1964const
1965{$ifdef CPU64}
1966  JSVAL_TAG_SHIFT              = 47;
1967  JSVAL_PAYLOAD_MASK           = $00007FFFFFFFFFFF;
1968  JSVAL_TAG_MASK               = $FFFF800000000000;
1969
1970  JSVAL_TAG_MAX_DOUBLE                = UInt32($1FFF0);
1971  JSVAL_TAG_INT32                     = UInt32(JSVAL_TAG_MAX_DOUBLE or UInt8(JSVAL_TYPE_INT32));
1972  JSVAL_TAG_UNDEFINED                 = UInt32(JSVAL_TAG_MAX_DOUBLE or UInt8(JSVAL_TYPE_UNDEFINED));
1973  JSVAL_TAG_STRING                    = UInt32(JSVAL_TAG_MAX_DOUBLE or UInt8(JSVAL_TYPE_STRING));
1974  JSVAL_TAG_SYMBOL                    = UInt32(JSVAL_TAG_MAX_DOUBLE or UInt8(JSVAL_TYPE_SYMBOL));
1975  JSVAL_TAG_BOOLEAN                   = UInt32(JSVAL_TAG_MAX_DOUBLE or UInt8(JSVAL_TYPE_BOOLEAN));
1976  JSVAL_TAG_MAGIC                     = UInt32(JSVAL_TAG_MAX_DOUBLE or UInt8(JSVAL_TYPE_MAGIC));
1977  JSVAL_TAG_NULL                      = UInt32(JSVAL_TAG_MAX_DOUBLE or UInt8(JSVAL_TYPE_NULL));
1978  JSVAL_TAG_OBJECT                    = UInt32(JSVAL_TAG_MAX_DOUBLE or UInt8(JSVAL_TYPE_OBJECT));
1979
1980  JSVAL_SHIFTED_TAG_MAX_DOUBLE        = (uint64(JSVAL_TAG_MAX_DOUBLE) shl JSVAL_TAG_SHIFT) or $FFFFFFFF;
1981  JSVAL_SHIFTED_TAG_INT32             = uint64(JSVAL_TAG_INT32) shl JSVAL_TAG_SHIFT;
1982  JSVAL_SHIFTED_TAG_UNDEFINED         = uint64(JSVAL_TAG_UNDEFINED) shl JSVAL_TAG_SHIFT;
1983  JSVAL_SHIFTED_TAG_STRING            = uint64(JSVAL_TAG_STRING) shl JSVAL_TAG_SHIFT;
1984  JSVAL_SHIFTED_TAG_SYMBOL            = uint64(JSVAL_TAG_SYMBOL) shl JSVAL_TAG_SHIFT;
1985  JSVAL_SHIFTED_TAG_BOOLEAN           = uint64(JSVAL_TAG_BOOLEAN) shl JSVAL_TAG_SHIFT;
1986  JSVAL_SHIFTED_TAG_MAGIC             = uint64(JSVAL_TAG_MAGIC) shl JSVAL_TAG_SHIFT;
1987  JSVAL_SHIFTED_TAG_NULL              = uint64(JSVAL_TAG_NULL) shl JSVAL_TAG_SHIFT;
1988  JSVAL_SHIFTED_TAG_OBJECT            = uint64(JSVAL_TAG_OBJECT) shl JSVAL_TAG_SHIFT;
1989{$endif}
1990
1991{$ifdef CPU64}
1992  JSVAL_NULL_impl =  QWord(JSVAL_SHIFTED_TAG_NULL);
1993  JSVAL_VOID_impl =  QWord(JSVAL_SHIFTED_TAG_UNDEFINED);
1994{$ELSE}
1995  JSVAL_NULL_impl =  QWord(QWord(JSVAL_TAG_NULL     ) shl 32) or 0;
1996  JSVAL_VOID_impl =  QWord(QWord(JSVAL_TAG_UNDEFINED) shl 32) or 0;
1997{$endif}
1998
1999  JSVAL_NAN_impl  =  $7FF8000000000000;
2000
2001const
2002  JSVAL_NULL: jsval = (_l:(asBits: JSVAL_NULL_impl));
2003  JSVAL_VOID: jsval = (_l:(asBits: JSVAL_VOID_impl));
2004  JSVAL_NAN:  jsval = (_l:(asBits: JSVAL_NAN_impl));
2005
2006const
2007  JSREPORT_ERROR = 0;
2008  JSREPORT_WARNING = 1;
2009  JSREPORT_EXCEPTION = 2;
2010  JSREPORT_STRICT = 4;
2011  JSREPORT_STRICT_MODE_ERROR = 8;
2012
2013function SimpleVariantToJSval(cx: PJSContext; val: Variant): jsval;
2014
2015const
2016  SpiderMonkeyLib = 'synsm'{$IFDEF MSWINDOWS} + '.dll'{$ENDIF};
2017
2018 /// Initialize SpiderMonkey, returning true only if initialization succeeded.
2019 // Once this method has succeeded, it is safe to call JS_NewRuntime and other
2020 // JSAPI methods.
2021 // - This method must be called before any other JSAPI method is used on any
2022 // thread.  Once it has been used, it is safe to call any JSAPI method, and it
2023 // remains safe to do so until JS_ShutDown is correctly called.
2024 // - It is currently not possible to initialize SpiderMonkey multiple times (that
2025 // is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
2026 // again).  This restriction may eventually be lifted.
2027type TJS_Initialize = function : Boolean; cdecl;
2028var JS_Init: TJS_Initialize external SpiderMonkeyLib name 'SM_Initialize';
2029
2030procedure JS_DisableExtraThreads; cdecl;
2031  external SpiderMonkeyLib name 'SM_DisableExtraThreads';
2032
2033 /// Destroy free-standing resources allocated by SpiderMonkey, not associated
2034 // with any runtime, context, or other structure.
2035 // - This method should be called after all other JSAPI data has been properly
2036 // cleaned up: every new runtime must have been destroyed, every new context
2037 // must have been destroyed, and so on.  Calling this method before all other
2038 // resources have been destroyed has undefined behavior.
2039 // - Failure to call this method, at present, has no adverse effects other than
2040 // leaking memory.  This may not always be the case; it's recommended that all
2041 // embedders call this method when all other JSAPI operations have completed.
2042 // - It is currently not possible to initialize SpiderMonkey multiple times (that
2043 // is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
2044 // again).  This restriction may eventually be lifted.
2045type TJS_ShutDown = procedure; cdecl;
2046var JS_ShutDown: TJS_ShutDown external SpiderMonkeyLib name 'SM_ShutDown';
2047
2048/// Microseconds since the epoch, midnight, January 1, 1970 UTC.
2049type TJS_Now = function : int64; cdecl;
2050var JS_Now: TJS_Now external SpiderMonkeyLib name 'SM_Now';
2051
2052/// Returns the empty string as a JSString object.
2053type TJS_GetEmptyString = function (cx: PJSContext): PJSString; cdecl;
2054var JS_GetEmptyString: TJS_GetEmptyString external SpiderMonkeyLib name 'SM_GetEmptyString';
2055
2056/// Determines the JS data type of a JS value.
2057type TJS_TypeOfValue = function (cx: PJSContext; var v: jsval): JSType; cdecl;
2058var JS_TypeOfValue: TJS_TypeOfValue external SpiderMonkeyLib name 'SM_TypeOfValue';
2059
2060/// indicates to the JS engine that the calling thread is entering a region
2061// of code that may call into the JSAPI but does not block
2062type TJS_BeginRequest = procedure (cx: PJSContext); cdecl;
2063var JS_BeginRequest: TJS_BeginRequest external SpiderMonkeyLib name 'SM_BeginRequest';
2064
2065/// indicates to the JS engine that the calling thread is leaving a region
2066// of code that may call into the JSAPI but does not block
2067type TJS_EndRequest = procedure (cx: PJSContext); cdecl;
2068var JS_EndRequest: TJS_EndRequest external SpiderMonkeyLib name 'SM_EndRequest';
2069
2070/// Create a new JSContext
2071type TJS_NewContext = function (maxbytes: uint32;
2072  maxNurseryBytes: uint32 = 16 * (1 SHL 20);
2073  parentContext: PJSContext = nil): PJSContext; cdecl;
2074var JS_NewContext: TJS_NewContext external SpiderMonkeyLib name 'SM_NewContext';
2075
2076type TInitSelfHostedCode = function (cx: PJSContext): boolean; cdecl;
2077var InitSelfHostedCode: TInitSelfHostedCode external SpiderMonkeyLib name 'SM_InitSelfHostedCode';
2078
2079/// Destroy a JSContext.
2080type TJS_DestroyContext = procedure (cx: PJSContext); cdecl;
2081var JS_DestroyContext: TJS_DestroyContext external SpiderMonkeyLib name 'SM_DestroyContext';
2082
2083/// Read access a JSContext field for application-specific data.
2084// Memory management for this private data is the application's responsibility.
2085// The JavaScript engine itself never uses it.
2086type TJS_GetContextPrivate = function (cx: PJSContext): Pointer; cdecl;
2087var JS_GetContextPrivate: TJS_GetContextPrivate external SpiderMonkeyLib name 'SM_GetContextPrivate';
2088
2089/// Write access a JSContext field for application-specific data.
2090// Memory management for this private data is the application's responsibility.
2091// The JavaScript engine itself never uses it.
2092type TJS_SetContextPrivate = procedure (cx: PJSContext; data: Pointer); cdecl;
2093var JS_SetContextPrivate: TJS_SetContextPrivate external SpiderMonkeyLib name 'SM_SetContextPrivate';
2094
2095/// This function makes a cross-compartment wrapper for the given JS object.
2096// Details see here http://stackoverflow.com/questions/18730477/what-does-js-wrapobject-do
2097type TJS_WrapObject = function (cx: PJSContext; var obj: PJSObject): boolean; cdecl;
2098var JS_WrapObject: TJS_WrapObject external SpiderMonkeyLib name 'SM_WrapObject';
2099
2100/// Enter a different compartment on the given context, so that objects in that
2101// compartment can be accessed.
2102// - NB: This API is infallible; a NULL return value does not indicate error
2103type TJS_EnterCompartment = function (cx: PJSContext; target: PJSObject): PJSCompartment; cdecl;
2104var JS_EnterCompartment: TJS_EnterCompartment external SpiderMonkeyLib name 'SM_EnterCompartment';
2105
2106/// Leave a the compartment, returning to the compartment active before the
2107// corresponding JS_EnterCompartment.
2108type TJS_LeaveCompartment = procedure (cx: PJSContext; oldCompartment: PJSCompartment); cdecl;
2109var JS_LeaveCompartment: TJS_LeaveCompartment external SpiderMonkeyLib name 'SM_LeaveCompartment';
2110
2111/// Initialize standard JS class constructors, prototypes, and any top-level
2112// functions and constants associated with the standard classes (e.g. isNaN
2113// for Number).
2114// - NB: This sets cx's global object to obj if it was null.
2115type TJS_InitStandardClasses = function (cx: PJSContext; var obj: PJSObject): boolean; cdecl;
2116var JS_InitStandardClasses: TJS_InitStandardClasses external SpiderMonkeyLib name 'SM_InitStandardClasses';
2117
2118///Return the global object for the active function on the context.
2119type TJS_CurrentGlobalOrNull = function (cx: PJSContext):PJSObject; cdecl;
2120var JS_CurrentGlobalOrNull: TJS_CurrentGlobalOrNull external SpiderMonkeyLib name 'SM_CurrentGlobalOrNull';
2121
2122/// Add 'Reflect.parse', a SpiderMonkey extension, to the Reflect object on the
2123// given global.
2124type TJS_InitReflectParse = function (cx: PJSContext; var obj: PJSObject): boolean; cdecl;
2125var JS_InitReflectParse: TJS_InitReflectParse external SpiderMonkeyLib name 'SM_InitReflectParse';
2126
2127/// Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes'
2128// object will be sealed.
2129type TJS_InitCTypesClass = function (cx: PJSContext; var obj: PJSObject): boolean; cdecl;
2130var JS_InitCTypesClass: TJS_InitCTypesClass external SpiderMonkeyLib name 'SM_InitCTypesClass';
2131
2132/// Initialize the 'Debugger' object on a global variable 'obj'. The 'ctypes'
2133// object will be sealed.
2134type TJS_DefineDebuggerObject = function (cx: PJSContext; var obj: PJSObject): boolean; cdecl;
2135var JS_DefineDebuggerObject: TJS_DefineDebuggerObject external SpiderMonkeyLib name 'SM_DefineDebuggerObject';
2136
2137/// Performs garbage collection in the JS memory pool.
2138type TJS_GC = procedure (cx: PJSContext); cdecl;
2139var JS_GC: TJS_GC external SpiderMonkeyLib name 'SM_GC';
2140
2141/// Offer the JavaScript engine an opportunity to perform garbage collection if needed.
2142type TJS_MaybeGC = procedure (cx: PJSContext); cdecl;
2143var JS_MaybeGC: TJS_MaybeGC external SpiderMonkeyLib name 'SM_MaybeGC';
2144
2145///Set performance parameters related to garbage collection.
2146type TJS_SetGCParameter = procedure (cx: PJSContext; key: JSGCParamKey; value: uint32); cdecl;
2147var JS_SetGCParameter: TJS_SetGCParameter external SpiderMonkeyLib name 'SM_SetGCParameter';
2148
2149///Get performance parameters related to garbage collection.
2150type TJS_GetGCParameter = function (cx: PJSContext; key: JSGCParamKey): uint32; cdecl;
2151var JS_GetGCParameter: TJS_GetGCParameter external SpiderMonkeyLib name 'SM_GetGCParameter';
2152
2153///Adjust performance parameters related to garbage collection based on available memory(in megabytes).
2154type TJS_SetGCParametersBasedOnAvailableMemory = procedure (cx: PJSContext; availMem: uint32); cdecl;
2155var JS_SetGCParametersBasedOnAvailableMemory: TJS_SetGCParametersBasedOnAvailableMemory external SpiderMonkeyLib name 'SM_SetGCParametersBasedOnAvailableMemory';
2156
2157/// Creates a new JSString whose characters are stored in external memory, i.e.,
2158//  memory allocated by the application, not the JavaScript engine
2159// - Since the program allocated the memory, it will need to free it;
2160//  this happens in an external string finalizer indicated by the type parameter.
2161// - chars is Pointer to the first element of an array of jschars.
2162//  This array is used as the character buffer of the JSString to be created.
2163//  The array must be populated with the desired character data before JS_NewExternalString
2164//  is called, and the array must remain in memory, with its contents unchanged,
2165//  for as long as the JavaScript engine needs to hold on to it.
2166// (Ultimately, the string will be garbage collected, and the JavaScript engine will
2167// call the string finalizer callback, allowing the application to free the array)
2168//  - The text buffer array does not need to be zero-terminated.
2169type TJS_NewExternalString = function (cx: PJSContext; chars: PCChar16; length: size_t;
2170  fin: PJSStringFinalizer): PJSString; cdecl;
2171var JS_NewExternalString: TJS_NewExternalString external SpiderMonkeyLib name 'SM_NewExternalString';
2172
2173/// Set the size of the native stack that should not be exceed. To disable
2174// stack size checking pass 0.
2175// - SpiderMonkey allows for a distinction between system code (such as GCs, which
2176// may incidentally be triggered by script but are not strictly performed on
2177// behalf of such script), trusted script (as determined by JS_SetTrustedPrincipals),
2178// and untrusted script. Each kind of code may have a different stack quota,
2179// allowing embedders to keep higher-priority machinery running in the face of
2180// scripted stack exhaustion by something else.
2181// - The stack quotas for each kind of code should be monotonically descending,
2182// and may be specified with this function. If 0 is passed for a given kind
2183// of code, it defaults to the value of the next-highest-priority kind.
2184// - This function may only be called immediately after the runtime is initialized
2185// and before any code is executed and/or interrupts requested.
2186type TJS_SetNativeStackQuota = procedure (cx: PJSContext; systemCodeStackSize: size_t;
2187  trustedScriptStackSize: size_t = 0; untrustedScriptStackSize: size_t = 0); cdecl;
2188var JS_SetNativeStackQuota: TJS_SetNativeStackQuota external SpiderMonkeyLib name 'SM_SetNativeStackQuota';
2189
2190/// Convert a JS::Value to type jsid.
2191type TJS_ValueToId = function (cx: PJSContext; var v: jsval; out id: jsid): Boolean; cdecl;
2192var JS_ValueToId: TJS_ValueToId external SpiderMonkeyLib name 'SM_ValueToId';
2193
2194/// Convert a jsid to type JS::Value.
2195type TJS_IdToValue = function (cx: PJSContext; id: jsid; out v: jsval): Boolean; cdecl;
2196var JS_IdToValue: TJS_IdToValue external SpiderMonkeyLib name 'SM_IdToValue';
2197
2198type TJS_ValueToSource = function (cx: PJSContext; var v: jsval): PJSString; cdecl;
2199var JS_ValueToSource: TJS_ValueToSource external SpiderMonkeyLib name 'SM_ValueToSource';
2200
2201/// Make a JSClass accessible to JavaScript code by creating its prototype,
2202// constructor, properties, and functions.
2203type TJS_InitClass = function (cx: PJSContext; var obj: PJSObject; var parent_proto: PJSObject;
2204  clasp: PJSClass; _constructor: JSNative; nargs: uintN;
2205  ps: PJSPropertySpec; fs: PJSFunctionSpec;
2206  static_ps: PJSPropertySpec; static_fs: PJSFunctionSpec): PJSObject; cdecl;
2207var JS_InitClass: TJS_InitClass external SpiderMonkeyLib name 'SM_InitClass';
2208
2209/// Retrieves the class associated with an object.
2210type TJS_GetClass = function (obj: PJSObject): PJSClass; cdecl;
2211var JS_GetClass: TJS_GetClass external SpiderMonkeyLib name 'SM_GetClass';
2212
2213/// JSAPI method equivalent to the instanceof operator in JavaScript.
2214type TJS_HasInstance = function (cx: PJSContext; var obj: PJSObject;
2215  var val: jsval; out res: Boolean): Boolean; cdecl;
2216var JS_HasInstance: TJS_HasInstance external SpiderMonkeyLib name 'SM_HasInstance';
2217
2218/// Access the private data field of an object.
2219type TJS_GetPrivate = function (obj: PJSObject): Pointer; cdecl;
2220var JS_GetPrivate: TJS_GetPrivate external SpiderMonkeyLib name 'SM_GetPrivate';
2221
2222/// Sets the private data field of an object.
2223type TJS_SetPrivate = procedure (obj: PJSObject; data: Pointer); cdecl;
2224var JS_SetPrivate: TJS_SetPrivate external SpiderMonkeyLib name 'SM_SetPrivate';
2225
2226/// Retrieves the constructor for an object.
2227type TJS_GetConstructor = function (cx: PJSContext; var proto: PJSObject): PJSObject; cdecl;
2228var JS_GetConstructor: TJS_GetConstructor external SpiderMonkeyLib name 'SM_GetConstructor';
2229
2230/// Retrieve the private data associated with an object, if that object is an
2231// instance of a specified class.
2232type TJS_GetInstancePrivate = function (cx: PJSContext; var obj: PJSObject;
2233  clasp: PJSClass; args: JSUnknown): Pointer; cdecl;
2234var JS_GetInstancePrivate: TJS_GetInstancePrivate external SpiderMonkeyLib name 'SM_GetInstancePrivate';
2235
2236/// Create a new JavaScript object for use as a global object.
2237type TJS_NewGlobalObject = function (cx: PJSContext; clasp: PJSClass; principals: PJSPrincipals;
2238  hookOption: OnNewGlobalHookOption; options: PJS_CompartmentOptions): PJSObject; cdecl;
2239var JS_NewGlobalObject: TJS_NewGlobalObject external SpiderMonkeyLib name 'SM_NewGlobalObject';
2240
2241/// Spidermonkey does not have a good way of keeping track of what compartments should be marked on
2242/// their own. We can mark the roots unconditionally, but marking GC things only relevant in live
2243/// compartments is hard. To mitigate this, we create a static trace hook, installed on each global
2244/// object, from which we can be sure the compartment is relevant, and mark it.
2245///
2246/// It is still possible to specify custom trace hooks for global object classes. They can be
2247/// provided via the CompartmentOptions passed to JS_NewGlobalObject.
2248type TJS_GlobalObjectTraceHook = procedure (trc: Pointer{ JSTracer }; global: PJSObject); cdecl;
2249var JS_GlobalObjectTraceHook: TJS_GlobalObjectTraceHook
2250  external SpiderMonkeyLib name 'SM_GlobalObjectTraceHook';
2251
2252/// Create a new object based on a specified class
2253type TJS_NewObject = function (cx: PJSContext; clasp: PJSClass): PJSObject; cdecl;
2254var JS_NewObject: TJS_NewObject external SpiderMonkeyLib name 'SM_NewObject';
2255
2256/// Create a new object based on a specified class
2257// - Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
2258// proto. If proto is nullptr, the JS object will have `null` as [[Prototype]].
2259type TJS_NewObjectWithGivenProto = function (cx: PJSContext; clasp: PJSClass;
2260  var proto: PJSObject): PJSObject; cdecl;
2261var JS_NewObjectWithGivenProto: TJS_NewObjectWithGivenProto external SpiderMonkeyLib name 'SM_NewObjectWithGivenProto';
2262
2263/// Get the prototype of obj, storing it in result.
2264// - Implements: ES6 [[GetPrototypeOf]] internal method.
2265type TJS_GetPrototype = function (cx: PJSContext; var obj: PJSObject;
2266  out result: PJSObject):Boolean; cdecl;
2267var JS_GetPrototype: TJS_GetPrototype external SpiderMonkeyLib name 'SM_GetPrototype';
2268
2269/// Change the prototype of obj.
2270// - Implements: ES6 [[SetPrototypeOf]] internal method.
2271// - In cases where ES6 [[SetPrototypeOf]] returns false without an exception,
2272// JS_SetPrototype throws a TypeError and returns false.
2273// - Performance warning: JS_SetPrototype is very bad for performance. It may
2274// cause compiled jit-code to be invalidated. It also causes not only obj but
2275// all other objects in the same "group" as obj to be permanently deoptimized.
2276// It's better to create the object with the right prototype from the start.
2277type TJS_SetPrototype = function (cx: PJSContext; var obj: PJSObject;
2278  var proto: PJSObject):Boolean; cdecl;
2279var JS_SetPrototype: TJS_SetPrototype external SpiderMonkeyLib name 'SM_SetPrototype';
2280
2281/// Create a new property on an object.
2282// Name indentifies by ID
2283type TJS_DefinePropertyById = function (cx: PJSContext; var obj: PJSObject;
2284  var id: jsid; var value: jsval; attrs: uint32; getter: JSNative;
2285  setter: JSNative): boolean; cdecl;
2286var JS_DefinePropertyById: TJS_DefinePropertyById external SpiderMonkeyLib name 'SM_DefinePropertyById';
2287
2288/// Create a new property on an object.
2289// Name indentifies by ansi string
2290type TJS_DefineProperty = function (cx: PJSContext; var obj: PJSObject;
2291  const name: PCChar; var value: jsval; attrs: uint32; getter: JSNative;
2292  setter: JSNative): boolean; cdecl;
2293var JS_DefineProperty: TJS_DefineProperty external SpiderMonkeyLib name 'SM_DefineProperty';
2294
2295/// Create a new property on an object.
2296// Name indentifies by unicode string
2297type TJS_DefineUCProperty = function (cx: PJSContext; var obj: PJSObject;
2298  const name: PCChar16; namelen: size_t; var value: jsval; attrs: uint32;
2299  getter: JSNative; setter: JSNative): Boolean; cdecl;
2300var JS_DefineUCProperty: TJS_DefineUCProperty external SpiderMonkeyLib name 'SM_DefineUCProperty';
2301
2302/// Determine whether a JavaScript object has a specified property.
2303// Name indentifies by ansi string
2304type TJS_HasProperty = function (cx: PJSContext; var obj: PJSObject;
2305  const name: PCChar; var found: Boolean): Boolean; cdecl;
2306var JS_HasProperty: TJS_HasProperty external SpiderMonkeyLib name 'SM_HasProperty';
2307
2308/// Determine whether a JavaScript object has a specified property.
2309// Name indentifies by unicode string
2310type TJS_HasUCProperty = function (cx: PJSContext; var obj: PJSObject;
2311  const name: PCChar16; namelen: size_t; var found: Boolean): Boolean; cdecl;
2312var JS_HasUCProperty: TJS_HasUCProperty external SpiderMonkeyLib name 'SM_HasUCProperty';
2313
2314/// Find a specified property and retrieve its value.
2315// Name indentifies by ID
2316type TJS_GetPropertyById = function (cx: PJSContext; var obj: PJSObject;
2317  var id: jsid; out vp: jsval): boolean; cdecl;
2318var JS_GetPropertyById: TJS_GetPropertyById external SpiderMonkeyLib name 'SM_GetPropertyById';
2319
2320/// Find a specified property and retrieve its value.
2321// Name indentifies by ansi string
2322type TJS_GetProperty = function (cx: PJSContext; var obj: PJSObject;
2323  const name: PCChar; out vp: jsval): boolean; cdecl;
2324var JS_GetProperty: TJS_GetProperty external SpiderMonkeyLib name 'SM_GetProperty';
2325
2326/// Find a specified property and retrieve its value.
2327// Name indentifies by unicode string
2328type TJS_GetUCProperty = function (cx: PJSContext; var obj: PJSObject;
2329  const name: PCChar16; namelen: size_t; out vp: jsval): boolean; cdecl;
2330var JS_GetUCProperty: TJS_GetUCProperty external SpiderMonkeyLib name 'SM_GetUCProperty';
2331
2332/// Find a specified numeric property of an object and return its current value.
2333type TJS_GetElement = function (cx: PJSContext; var obj: PJSObject; index: uint32;
2334  out vp: jsval): Boolean; cdecl;
2335var JS_GetElement: TJS_GetElement external SpiderMonkeyLib name 'SM_GetElement';
2336
2337/// Assign a value to a property of an object.
2338// Name indentifies by ansi string
2339type TJS_SetProperty = function (cx: PJSContext; var obj: PJSObject;
2340  const name: PCChar; var vp: jsval): Boolean; cdecl;
2341var JS_SetProperty: TJS_SetProperty external SpiderMonkeyLib name 'SM_SetProperty';
2342
2343/// Assign a value to a property of an object.
2344// Name indentifies by unicode string
2345type TJS_SetUCProperty = function (cx: PJSContext; var obj: PJSObject;
2346  const name: PCChar16; namelen: size_t; var vp: jsval): boolean; cdecl;
2347var JS_SetUCProperty: TJS_SetUCProperty external SpiderMonkeyLib name 'SM_SetUCProperty';
2348
2349/// Assign a value to a numeric property of an object.
2350type TJS_SetElement = function (cx: PJSContext; var obj: PJSObject; index: uint32;
2351  var vp: jsval): Boolean; cdecl;
2352var JS_SetElement: TJS_SetElement external SpiderMonkeyLib name 'SM_SetElement';
2353
2354/// Removes a specified property from an object.
2355// Name indentifies by ID
2356type TJS_DeletePropertyById = function (cx: PJSContext; var obj: PJSObject;
2357  var id: jsid; out res: JS_ObjectOpResult): Boolean; cdecl;
2358var JS_DeletePropertyById: tJS_DeletePropertyById external SpiderMonkeyLib name 'SM_DeletePropertyById';
2359
2360/// Removes a specified element or numeric property from an object.
2361type TJS_DeleteElement = function (cx: PJSContext; var obj: PJSObject;
2362  index: uint32; out res: JS_ObjectOpResult): Boolean; cdecl;
2363var JS_DeleteElement: TJS_DeleteElement external SpiderMonkeyLib name 'SM_DeleteElement';
2364
2365/// Get an array of the non-symbol enumerable properties of obj.
2366// This function is roughly equivalent to:
2367//
2368//     var result = [];
2369//     for (key in obj)
2370//         result.push(key);
2371//     return result;
2372//
2373// This is the closest thing we currently have to the ES6 [[Enumerate]]
2374// internal method.
2375//
2376// The JSIdArray returned is rooted to protect its
2377// contents from garbage collection.
2378function JS_EnumerateToAutoIdVector(cx: PJSContext; var obj: PJSObject;
2379  out length: size_t; out data: PjsidVector): PJSIdArray;
2380  cdecl; external SpiderMonkeyLib name 'SM_EnumerateToAutoIdVector';
2381
2382procedure JS_DestroyAutoIdVector(v: PJSIdArray);
2383  cdecl; external SpiderMonkeyLib name 'SM_DestroyAutoIdVector';
2384
2385type
2386  JSHandleValueArray = record
2387    length: size_t;
2388    elements_: PjsvalVector;
2389  end;
2390
2391/// Calls a specified JS function.
2392// Function identifies by jsvalue
2393// - equivalent of `rval = Reflect.apply(fun, obj, args)`.
2394type TJS_CallFunctionValue = function (cx: PJSContext; var obj: PJSObject;
2395  var val: jsval; var args: JSHandleValueArray; out rval: jsval): Boolean; cdecl;
2396var JS_CallFunctionValue: TJS_CallFunctionValue external SpiderMonkeyLib name 'SM_CallFunctionValue';
2397
2398/// Calls a specified JS function.
2399// Function identifies by PJSFunction
2400type TJS_CallFunction = function (cx: PJSContext; var obj: PJSObject;
2401  var fun: PJSFunction; var args: JSHandleValueArray; out rval: jsval): Boolean; cdecl;
2402var JS_CallFunction: TJS_CallFunction external SpiderMonkeyLib name 'SM_CallFunction';
2403
2404/// Calls a specified JS function.
2405// Function identifies by ansi string
2406// - Perform the method call `rval = obj[name](args)`.
2407type TJS_CallFunctionName = function (cx: PJSContext; var obj: PJSObject;
2408  const name: PCChar; var args: JSHandleValueArray; out rval: jsval): Boolean; cdecl;
2409var JS_CallFunctionName: TJS_CallFunctionName external SpiderMonkeyLib name 'SM_CallFunctionName';
2410
2411/// Invoke a constructor, like the JS expression `new ctor(...args)`. Returns
2412// the new object, or null on error.
2413type TJS_New = function (cx: PJSContext; var ctor: PJSObject;
2414  var args: JSHandleValueArray): PJSObject; cdecl;
2415var JS_New: TJS_New external SpiderMonkeyLib name 'SM_New';
2416
2417/// Define multiple properties for a single object.
2418type TJS_DefineProperties = function (cx: PJSContext; var obj: PJSObject;
2419  ps: PJSPropertySpec): boolean; cdecl;
2420var JS_DefineProperties: TJS_DefineProperties external SpiderMonkeyLib name 'SM_DefineProperties';
2421
2422/// Determine whether a property is already physically present on a JSObject.
2423// Name indentifies by unicode string
2424type TJS_AlreadyHasOwnUCProperty = function (cx: PJSContext; var obj: PJSObject;
2425    const name: PCChar16; namelen: size_t; var foundp: Boolean): Boolean; cdecl;
2426var JS_AlreadyHasOwnUCProperty: TJS_AlreadyHasOwnUCProperty external SpiderMonkeyLib name 'SM_AlreadyHasOwnUCProperty';
2427
2428/// Create a new Array object.
2429// Only length passed
2430type TJS_NewArrayObject = function (cx: PJSContext; length: size_t): PJSObject; cdecl;
2431var JS_NewArrayObject: TJS_NewArrayObject external SpiderMonkeyLib name 'SM_NewArrayObject';
2432
2433/// Create a new Array object.
2434// Content passed
2435type TJS_NewArrayObject2 = function (cx: PJSContext;
2436    const contents: JSHandleValueArray): PJSObject; cdecl;
2437var JS_NewArrayObject2: TJS_NewArrayObject2 external SpiderMonkeyLib name 'SM_NewArrayObject2';
2438
2439/// Returns true and sets |*isArray| indicating whether |obj| is an Array object
2440// or a wrapper around one, otherwise returns false on failure.
2441// - This method returns true with |*isArray == false| when passed a proxy whose
2442// target is an Array, or when passed a revoked proxy.
2443type TJS_IsArrayObject = function (cx: PJSContext; var obj: PJSObject;
2444    out isArray: Boolean): boolean; cdecl;
2445var JS_IsArrayObject: TJS_IsArrayObject external SpiderMonkeyLib name 'SM_IsArrayObject';
2446
2447/// JS_GetArrayLength gets the .length property of obj as though by calling JS_GetProperty
2448// and converts it to a 32-bit unsigned integer. If obj is an array (see JS_IsArrayObject),
2449// this is guaranteed to succeed, because the .length property of an array is always a number
2450// and can't be deleted or redefined.
2451// - On success, JS_GetArrayLength stores the length in *lengthp and returns true.
2452// On failure, it reports an error and returns false, and the value left in *lengthp
2453// is undefined.
2454type TJS_GetArrayLength = function (cx: PJSContext; var obj: PJSObject;
2455  out length: uint32): Boolean; cdecl;
2456var JS_GetArrayLength: TJS_GetArrayLength external SpiderMonkeyLib name 'SM_GetArrayLength';
2457
2458/// Read access an object's reserved slots.
2459function JS_GetReservedSlot(obj: PJSObject; index: uint32): Int64; cdecl;
2460  external SpiderMonkeyLib name 'SM_GetReservedSlot';
2461
2462/// Write access an object's reserved slots
2463type TJS_SetReservedSlot = procedure (obj: PJSObject; index: uint32;
2464  var v: jsval); cdecl;
2465var JS_SetReservedSlot: TJS_SetReservedSlot external SpiderMonkeyLib name 'SM_SetReservedSlot';
2466
2467/// Create a new JavaScript function that is implemented as a JSNative.
2468type TJS_NewFunction = function (cx: PJSContext; call: JSNative; nargs: uintN;
2469  flags: uintN; name: PCChar): PJSObject; cdecl;
2470var JS_NewFunction: TJS_NewFunction external SpiderMonkeyLib name 'SM_NewFunction';
2471
2472/// Return the function's identifier as a JSString, or null if fun is unnamed.
2473// The returned string lives as long as fun, so you don't need to root a saved
2474// reference to it if fun is well-connected or rooted, and provided you bound
2475// the use of the saved reference by fun's lifetime.
2476type TJS_GetFunctionId = function (fun: PJSFunction): PJSString; cdecl;
2477var JS_GetFunctionId: TJS_GetFunctionId external SpiderMonkeyLib name 'SM_GetFunctionId';
2478
2479/// Infallible predicate to test whether obj is a function object (faster than
2480// comparing obj's class name to "Function", but equivalent unless someone has
2481// overwritten the "Function" identifier with a different constructor and then
2482// created instances using that constructor that might be passed in as obj).
2483type TJS_ObjectIsFunction = function (cx: PJSContext; obj: PJSObject): boolean; cdecl;
2484var JS_ObjectIsFunction: TJS_ObjectIsFunction external SpiderMonkeyLib name 'SM_ObjectIsFunction';
2485
2486/// Create zero or more functions and makes them properties (methods)
2487// of a specified object, obj, as if by calling JS_DefineFunction repeatedly
2488type TJS_DefineFunctions = function (cx: PJSContext; var obj: PJSObject;
2489  fs: PJSFunctionSpec; behavior: JSPropertyDefinitionBehavior): Boolean; cdecl;
2490var JS_DefineFunctions: TJS_DefineFunctions external SpiderMonkeyLib name 'SM_DefineFunctions';
2491
2492/// Create a native function and assign it as a property to a specified JS object
2493type TJS_DefineFunction = function (cx: PJSContext; var obj: PJSObject; name: PCChar;
2494    call: JSNative; nargs: uintN; attrs: uintN): PJSFunction; cdecl;
2495var JS_DefineFunction: TJS_DefineFunction external SpiderMonkeyLib name 'SM_DefineFunction';
2496
2497/// Unicode version to create a native function
2498type TJS_DefineUCFunction = function (cx: PJSContext; var obj: PJSObject;
2499    name: PCChar16; namelen: size_t; call: JSNative; nargs: uintN;
2500    attrs: uintN): PJSFunction; cdecl;
2501var JS_DefineUCFunction: TJS_DefineUCFunction external SpiderMonkeyLib name 'SM_DefineUCFunction';
2502
2503/// Compile a script, source, for execution.
2504// Ansi version
2505type TJS_CompileScript = function (cx: PJSContext; bytes: PCChar; length: size_t;
2506  options: PJSCompileOptions; out script: PJSScript): boolean; cdecl;
2507var JS_CompileScript: TJS_CompileScript external SpiderMonkeyLib name 'SM_CompileScript';
2508
2509/// Compile a script, source, for execution.
2510// Unicode version
2511type TJS_CompileUCScript = function (cx: PJSContext; chars: PCChar16;
2512  length: size_t; options: PJSCompileOptions; out script: PJSScript): boolean; cdecl;
2513var JS_CompileUCScript: TJS_CompileUCScript external SpiderMonkeyLib name 'SM_CompileUCScript';
2514
2515/// Generate the complete source code of a function declaration from a compiled function
2516type TJS_DecompileFunction = function (cx: PJSContext; var fun: PJSFunction;
2517  indent: uintN): PJSString; cdecl;
2518var JS_DecompileFunction: TJS_DecompileFunction external SpiderMonkeyLib name 'SM_DecompileFunction';
2519
2520/// Evaluate a script in the scope of the current global of cx.
2521type TJS_ExecuteScript = function (cx: PJSContext; var script: PJSScript;
2522  out rval: jsval): Boolean; cdecl;
2523var JS_ExecuteScript: TJS_ExecuteScript external SpiderMonkeyLib name 'SM_ExecuteScript';
2524
2525/// These functions allow setting an interrupt callback that will be called
2526// from the JS thread some time after any thread triggered the callback using
2527// JS_RequestInterruptCallback(cx).
2528// - To schedule the GC and for other activities the engine internally triggers
2529// interrupt callbacks. The embedding should thus not rely on callbacks being
2530//triggered through the external API only.
2531// - Important note: Additional callbacks can occur inside the callback handler
2532// if it re-enters the JS engine. The embedding must ensure that the callback
2533// is disconnected before attempting such re-entry.
2534type TJS_CheckForInterrupt = function (cx: PJSContext): Boolean; cdecl;
2535var JS_CheckForInterrupt: TJS_CheckForInterrupt external SpiderMonkeyLib name 'SM_CheckForInterrupt';
2536
2537type TJS_AddInterruptCallback = function (cx: PJSContext;
2538  callback: JSInterruptCallback): Boolean; cdecl;
2539var JS_AddInterruptCallback: TJS_AddInterruptCallback external SpiderMonkeyLib name 'SM_AddInterruptCallback';
2540
2541type TJS_DisableInterruptCallback = function (cx: PJSContext): Boolean; cdecl;
2542var JS_DisableInterruptCallback: TJS_DisableInterruptCallback external SpiderMonkeyLib name 'SM_DisableInterruptCallback';
2543
2544type TJS_ResetInterruptCallback = procedure (cx: PJSContext;
2545  enable: Boolean); cdecl;
2546var JS_ResetInterruptCallback: TJS_ResetInterruptCallback external SpiderMonkeyLib name 'SM_ResetInterruptCallback';
2547
2548/// Request a callback set using JS_SetInterruptCallback
2549type TJS_RequestInterruptCallback = procedure (cx: PJSContext); cdecl;
2550var JS_RequestInterruptCallback: TJS_RequestInterruptCallback external SpiderMonkeyLib name 'SM_RequestInterruptCallback';
2551
2552/// Indicates whether or not a script or function is currently executing in a given context.
2553type TJS_IsRunning = function (cx: PJSContext): Boolean; cdecl;
2554var JS_IsRunning: TJS_IsRunning external SpiderMonkeyLib name 'SM_IsRunning';
2555
2556/// Allocate space for a JavaScript string and its underlying storage,
2557// and copy n characters from a character array, s, into the new JSString
2558// Ansi version
2559type TJS_NewStringCopyN = function (cx: PJSContext; s: PCChar;
2560  n: size_t): PJSString; cdecl;
2561var JS_NewStringCopyN: TJS_NewStringCopyN external SpiderMonkeyLib name 'SM_NewStringCopyN';
2562
2563// TODO - recompile libsynsm with exported SM_AtomizeAndPinStringN
2564//type TJS_AtomizeAndPinStringN = function (cx: PJSContext; s: PCChar;
2565//  n: size_t): PJSString; cdecl;
2566//var JS_AtomizeAndPinStringN: TJS_AtomizeAndPinStringN external SpiderMonkeyLib name 'SM_AtomizeAndPinStringN';
2567
2568
2569/// Allocate space for a JavaScript string and its underlying storage,
2570// and copy characters from NULL TERMINATED! UTF8 character array
2571type TJS_NewStringCopyUTF8Z = function (cx: PJSContext;
2572  pNullTerminatedUTF8: PUTF8Char): PJSString; cdecl;
2573var JS_NewStringCopyUTF8Z: TJS_NewStringCopyUTF8Z external SpiderMonkeyLib name 'SM_NewStringCopyUTF8Z';
2574
2575
2576/// Returns the empty JSString as a JS value
2577type TJS_GetEmptyStringValue = function (cx: PJSContext): jsval; cdecl;
2578var JS_GetEmptyStringValue: TJS_GetEmptyStringValue external SpiderMonkeyLib name 'SM_GetEmptyStringValue';
2579
2580/// Allocate space for a JavaScript string and its underlying storage,
2581// and copy n characters from a character array, s, into the new JSString
2582// Unicode version
2583type TJS_NewUCStringCopyN = function (cx: PJSContext; s: PCChar16;
2584  n: size_t): PJSString; cdecl;
2585var JS_NewUCStringCopyN: TJS_NewUCStringCopyN external SpiderMonkeyLib name 'SM_NewUCStringCopyN';
2586
2587/// Return the length of a JavaScript string.
2588type TJS_GetStringLength = function (str: PJSString): size_t; cdecl;
2589var JS_GetStringLength: TJS_GetStringLength external SpiderMonkeyLib name 'SM_GetStringLength';
2590
2591/// Return true if the string's characters are stored as Latin1.
2592type TJS_StringHasLatin1Chars = function (str: PJSString): boolean; cdecl;
2593var JS_StringHasLatin1Chars: TJS_StringHasLatin1Chars external SpiderMonkeyLib name 'SM_StringHasLatin1Chars';
2594
2595/// Return a pointer to the string, and store the length to *length
2596// Use it when characters are stored as Latin1.
2597type TJS_GetLatin1StringCharsAndLength = function (cx: PJSContext;
2598  nogc: PJSAutoCheckCannotGC; str: PJSString; plength: psize_t):PCChar; cdecl;
2599var JS_GetLatin1StringCharsAndLength: TJS_GetLatin1StringCharsAndLength external SpiderMonkeyLib name 'SM_GetLatin1StringCharsAndLength';
2600
2601/// Return a pointer to the string, and store the length to *length
2602// Use it when characters are stored as Unicode
2603type TJS_GetTwoByteStringCharsAndLength = function (cx: PJSContext;
2604  nogc: PJSAutoCheckCannotGC; str: PJSString; plength: psize_t): PCChar16; cdecl;
2605var JS_GetTwoByteStringCharsAndLength: TJS_GetTwoByteStringCharsAndLength external SpiderMonkeyLib name 'SM_GetTwoByteStringCharsAndLength';
2606
2607/// converts a value to JSON, optionally replacing values if a replacer
2608// function is specified, or optionally including only the specified properties
2609// if a replacer array is specified
2610type TJS_Stringify = function (cx: PJSContext; var vp: jsval;
2611  var replacer: PJSObject; var space: jsval; callback: JSONWriteCallback;
2612  data: pointer): Boolean; cdecl;
2613var JS_Stringify: TJS_Stringify external SpiderMonkeyLib name 'SM_Stringify';
2614
2615/// parse a string using the JSON syntax described in ECMAScript 5 and
2616// return the corresponding value into vp
2617type TJS_ParseJSON = function (cx: PJSContext; const chars: PCChar16;
2618  len: uint32; out vp: jsval): Boolean; cdecl;
2619var JS_ParseJSON: TJS_ParseJSON external SpiderMonkeyLib name 'SM_ParseJSON';
2620
2621/// Create a new JavaScript Error object and set it to be the pending exception on cx.
2622// The callback must then return JS_FALSE to cause the exception to be propagated
2623// to the calling script.
2624type TJS_ReportError = procedure (cx: PJSContext; const format: PCChar); cdecl; varargs;
2625var JS_ReportError: TJS_ReportError external SpiderMonkeyLib name 'SM_ReportErrorASCII';
2626
2627/// Report an error with an application-defined error code.
2628// - varargs is Additional arguments for the error message.
2629//- These arguments must be of type jschar*
2630// - The number of additional arguments required depends on the error
2631// message, which is determined by the errorCallback
2632type TJS_ReportErrorNumberUC = procedure (cx: PJSContext; errorCallback: JSErrorCallback;
2633  userRef: pointer; const erroNubmer: uintN); cdecl; varargs;
2634var JS_ReportErrorNumberUC: TJS_ReportErrorNumberUC external SpiderMonkeyLib name 'SM_ReportErrorNumberUC';
2635
2636type TJS_ReportErrorNumberUTF8 = procedure (cx: PJSContext;
2637  errorCallback: JSErrorCallback; userRef: pointer;
2638  const erroNubmer: uintN); cdecl; varargs;
2639var JS_ReportErrorNumberUTF8: TJS_ReportErrorNumberUTF8 external SpiderMonkeyLib name 'SM_ReportErrorNumberUTF8';
2640
2641/// Reports a memory allocation error
2642// - Call JS_ReportOutOfMemory to report that an operation failed because the
2643// system is out of memory
2644// - When the JavaScript engine tries to allocate memory and allocation fails,
2645// it reports an error as though by calling this function
2646type TJS_ReportOutOfMemory = procedure (cx: PJSContext); cdecl;
2647var JS_ReportOutOfMemory: TJS_ReportOutOfMemory external SpiderMonkeyLib name 'SM_ReportOutOfMemory';
2648
2649/// Get the warning reporting mechanism for an application. It is not working for errors.
2650type TJS_GetWarningReporter = function (cx: PJSContext): JSWarningReporter; cdecl;
2651var JS_GetWarningReporter: TJS_GetWarningReporter external SpiderMonkeyLib name 'SM_GetWarningReporter';
2652
2653/// Specify the warning reporting mechanism for an application.  It is not working for errors.
2654type TJS_SetWarningReporter = function (cx: PJSContext;
2655  reporter: JSWarningReporter): JSWarningReporter; cdecl;
2656var JS_SetWarningReporter: TJS_SetWarningReporter external SpiderMonkeyLib name 'SM_SetWarningReporter';
2657
2658/// Create a new JavaScript date object
2659type TJS_NewDateObject = function (cx: PJSContext;
2660  year, mon, mday, hour, min, sec: int32): PJSObject; cdecl;
2661var JS_NewDateObject: TJS_NewDateObject external SpiderMonkeyLib name 'SM_NewDateObject';
2662
2663/// Create a new JavaScript date object from the Unix millisecond elapsed since EPOC
2664function JS_NewDateObjectMsec(cx: PJSContext; msec: double): PJSObject; cdecl;
2665  external SpiderMonkeyLib name 'SM_NewDateObjectMsec';
2666
2667// Returns true and sets |*isDate| indicating whether |obj| is a Date object or
2668// a wrapper around one, otherwise returns false on failure.
2669// - This method returns true with |*isDate == false| when passed a proxy whose
2670// target is a Date, or when passed a revoked proxy.
2671type TJS_ObjectIsDate = function (cx: PJSContext; var obj: PJSObject;
2672  out isDate: boolean): boolean; cdecl;
2673var JS_ObjectIsDate: TJS_ObjectIsDate external SpiderMonkeyLib name 'SM_ObjectIsDate';
2674
2675/// Determine whether an exception is pending in the JS engine.
2676type TJS_IsExceptionPending = function (cx: PJSContext): Boolean; cdecl;
2677var JS_IsExceptionPending: TJS_IsExceptionPending external SpiderMonkeyLib name 'SM_IsExceptionPending';
2678
2679/// Get the current pending exception for a given JSContext.
2680type TJS_GetPendingException = function (cx: PJSContext;
2681  out vp: jsval): Boolean; cdecl;
2682var JS_GetPendingException: TJS_GetPendingException external SpiderMonkeyLib name 'SM_GetPendingException';
2683
2684/// Sets the current exception being thrown within a context.
2685type TJS_SetPendingException = procedure (cx: PJSContext; var vp: jsval); cdecl;
2686var JS_SetPendingException: TJS_SetPendingException external SpiderMonkeyLib name 'SM_SetPendingException';
2687
2688/// Clear the currently pending exception in a context.
2689type TJS_ClearPendingException = procedure (cx: PJSContext); cdecl;
2690var JS_ClearPendingException: TJS_ClearPendingException external SpiderMonkeyLib name 'SM_ClearPendingException';
2691
2692/// If the given object is an exception object, the exception will have (or be
2693// able to lazily create) an error report struct, and this function will return
2694// the address of that struct.  Otherwise, it returns nullptr. The lifetime
2695// of the error report struct that might be returned is the same as the
2696// lifetime of the exception object.
2697type TJS_ErrorFromException = function (cx: PJSContext;
2698  var obj: PJSObject): PJSErrorReport; cdecl;
2699var JS_ErrorFromException: TJS_ErrorFromException external SpiderMonkeyLib name 'SM_ErrorFromException';
2700
2701/// Get options of context
2702function JS_GetContextOptions(cx: PJSContext): PJSContextOptions; cdecl;
2703  external SpiderMonkeyLib name 'SM_GetContextOptions';
2704
2705//function JS_NewRootedValue(cx: PJSContext; val: jsval): PJSRootedValue; cdecl; external SpiderMonkeyLib;
2706function JS_NewRootedValue(cx: PJSContext; val: Int64): PJSRootedValue; cdecl;
2707  external SpiderMonkeyLib name 'SM_NewRootedValue';
2708
2709procedure JS_FreeRootedValue(val: PJSRootedValue); cdecl;
2710  external SpiderMonkeyLib name 'SM_FreeRootedValue';
2711
2712function JS_NewRootedObject(cx: PJSContext; obj: PJSObject): PJSRootedObject; cdecl;
2713  external SpiderMonkeyLib name 'SM_NewRootedObject';
2714
2715procedure JS_FreeRootedObject(obj: PJSRootedObject); cdecl;
2716  external SpiderMonkeyLib name 'SM_FreeRootedObject';
2717
2718function JS_NewRootedString(cx: PJSContext; obj: PJSString): PJSRootedString; cdecl;
2719  external SpiderMonkeyLib name 'SM_NewRootedString';
2720
2721procedure JS_FreeRootedString(str: PJSRootedString); cdecl;
2722  external SpiderMonkeyLib name 'SM_FreeRootedString';
2723
2724/// Create Compile Options
2725function JS_NewCompileOptions(cx: PJSContext): PJSCompileOptions; cdecl;
2726  external SpiderMonkeyLib name 'SM_NewCompileOptions';
2727
2728/// expose to Pascal
2729// JS::CompileOptions.setFileAndLine + setUTF8
2730procedure JS_SetCompileOptionsFileLineAndUtf8(co: PJSCompileOptions;
2731  const f: PChar; l: cardinal; isUtf8: boolean); cdecl;
2732  external SpiderMonkeyLib name 'SM_SetCompileOptionsFileLineAndUtf8';
2733
2734/// Free Compile Options
2735procedure JS_FreeCompileOptions(opt: PJSCompileOptions); cdecl;
2736  external SpiderMonkeyLib name 'SM_FreeCompileOptions';
2737///////////////////
2738
2739type TJS_EvaluateScript = function (cx: PJSContext;
2740   options: PJSCompileOptions; bytes: PCChar; length: size_t;
2741   out rval: jsval): Boolean; cdecl;
2742var JS_EvaluateScript: TJS_EvaluateScript external SpiderMonkeyLib name 'SM_EvaluateScript';
2743
2744type TJS_EvaluateUCScript = function (cx: PJSContext;
2745   options: PJSCompileOptions; chars: PCChar16; length: size_t;
2746   out rval: jsval): Boolean; cdecl;
2747var JS_EvaluateUCScript: TJS_EvaluateUCScript external SpiderMonkeyLib name 'SM_EvaluateUCScript';
2748
2749/// Compute |this| for the |vp| inside a JSNative, either boxing primitives or
2750// replacing with the global object as necessary.
2751// - This method will go away at some point: instead use |args.thisv()|.  If the
2752// value is an object, no further work is required.  If that value is |null| or
2753// |undefined|, use |JS_GetGlobalForObject| to compute the global object.  If
2754// the value is some other primitive, use |JS_ValueToObject| to box it.
2755// - low-level API used by JS_THIS() macro.
2756//function JS_ComputeThis(cx: PJSContext; var vp: jsval): jsval; cdecl; external SpiderMonkeyLib;
2757type TJS_ComputeThis = function (cx: PJSContext; var vp: jsval): Int64; cdecl;
2758var JS_ComputeThis: TJS_ComputeThis external SpiderMonkeyLib name 'SM_ComputeThis';
2759
2760procedure strFinalizeOp(fin: PJSStringFinalizer; chars: PCChar16); cdecl;
2761const
2762  strFinalizer: JSStringFinalizer = (
2763    finalize: strFinalizeOp;
2764  );
2765
2766{ ArrayBuffer support from jsfriendapi.h}
2767
2768/// Create a new signed 8 bit integer typed array with nelements elements
2769// - will fill the newly created array with zeros
2770type TJS_NewInt8Array = function (cx: PJSContext;
2771  nelements: uint32): PJSObject; cdecl;
2772var JS_NewInt8Array: TJS_NewInt8Array external SpiderMonkeyLib name 'SM_NewInt8Array';
2773
2774/// Create a new unsigned 8 bit integer (byte) typed array with nelements elements
2775// - will fill the newly created array with zeros
2776type TJS_NewUint8Array = function (cx: PJSContext;
2777  nelements: uint32): PJSObject; cdecl;
2778var JS_NewUint8Array: TJS_NewUint8Array external SpiderMonkeyLib name 'SM_NewUint8Array';
2779
2780/// Create a new 8 bit integer typed array with nelements elements
2781// - will fill the newly created array with zeros
2782type TJS_NewUint8ClampedArray = function (cx: PJSContext;
2783  nelements: uint32): PJSObject; cdecl;
2784var JS_NewUint8ClampedArray: TJS_NewUint8ClampedArray external SpiderMonkeyLib name 'SM_NewUint8ClampedArray';
2785
2786/// Create a new signed 16 bit integer typed array with nelements elements
2787// - will fill the newly created array with zeros
2788type TJS_NewInt16Array = function (cx: PJSContext;
2789  nelements: uint32): PJSObject; cdecl;
2790var JS_NewInt16Array: TJS_NewInt16Array external SpiderMonkeyLib name 'SM_NewInt16Array';
2791
2792/// Create a new unsigned 16 bit integer typed array with nelements elements
2793// - will fill the newly created array with zeros
2794type TJS_NewUint16Array = function (cx: PJSContext;
2795  nelements: uint32): PJSObject; cdecl;
2796var JS_NewUint16Array: TJS_NewUint16Array external SpiderMonkeyLib name 'SM_NewUint16Array';
2797
2798/// Create a new signed 32 bit integer typed array with nelements elements
2799// - will fill the newly created array with zeros
2800type TJS_NewInt32Array = function (cx: PJSContext;
2801  nelements: uint32): PJSObject; cdecl;
2802var JS_NewInt32Array: TJS_NewInt32Array external SpiderMonkeyLib name 'SM_NewInt32Array';
2803
2804/// Create a new unsigned 32 bit integer typed array with nelements elements
2805// - will fill the newly created array with zeros
2806type TJS_NewUint32Array = function (cx: PJSContext;
2807  nelements: uint32): PJSObject; cdecl;
2808var JS_NewUint32Array: TJS_NewUint32Array external SpiderMonkeyLib name 'SM_NewUint32Array';
2809
2810/// Create a new signed 32 bit float (single) typed array with nelements elements
2811// - will fill the newly created array with zeros
2812type TJS_NewFloat32Array = function (cx: PJSContext;
2813  nelements: uint32): PJSObject; cdecl;
2814var JS_NewFloat32Array: TJS_NewFloat32Array external SpiderMonkeyLib name 'SM_NewFloat32Array';
2815
2816/// Create a new signed 64 bit float (double) typed array with nelements elements
2817// - will fill the newly created array with zeros
2818type TJS_NewFloat64Array = function (cx: PJSContext;
2819  nelements: uint32): PJSObject; cdecl;
2820var JS_NewFloat64Array: TJS_NewFloat64Array external SpiderMonkeyLib name 'SM_NewFloat64Array';
2821
2822/// Create a new 8 bit signed integer typed array and copy in values
2823// from a given object
2824// - The object is used as if it was an array; that is, the new array (if
2825// successfully created) will have length given by array.length, and its
2826// elements will be those specified by array[0], array[1], and so on, after
2827// conversion to the typed array element type.
2828type TJS_NewInt8ArrayFromArray = function (cx: PJSContext;
2829  var arr: PJSObject): PJSObject; cdecl;
2830var JS_NewInt8ArrayFromArray: TJS_NewInt8ArrayFromArray external SpiderMonkeyLib name 'SM_NewInt8ArrayFromArray';
2831
2832/// Create a new 8 bit unsigned integer typed array and copy in values
2833// from a given object
2834// - The object is used as if it was an array; that is, the new array (if
2835// successfully created) will have length given by array.length, and its
2836// elements will be those specified by array[0], array[1], and so on, after
2837// conversion to the typed array element type.
2838type TJS_NewUint8ArrayFromArray = function (cx: PJSContext;
2839  var arr: PJSObject): PJSObject; cdecl;
2840var JS_NewUint8ArrayFromArray: TJS_NewUint8ArrayFromArray external SpiderMonkeyLib name 'SM_NewUint8ArrayFromArray';
2841
2842/// Create a new 8 bit unsigned integer typed array and copy in values
2843// from a given object
2844// - The object is used as if it was an array; that is, the new array (if
2845// successfully created) will have length given by array.length, and its
2846// elements will be those specified by array[0], array[1], and so on, after
2847// conversion to the typed array element type.
2848type TJS_NewUint8ClampedArrayFromArray = function (cx: PJSContext;
2849  var arr: PJSObject): PJSObject; cdecl;
2850var JS_NewUint8ClampedArrayFromArray: TJS_NewUint8ClampedArrayFromArray external SpiderMonkeyLib name 'SM_NewUint8ClampedArrayFromArray';
2851
2852/// Create a new 16 bit signed integer typed array and copy in values
2853// from a given object
2854// - The object is used as if it was an array; that is, the new array (if
2855// successfully created) will have length given by array.length, and its
2856// elements will be those specified by array[0], array[1], and so on, after
2857// conversion to the typed array element type.
2858type TJS_NewInt16ArrayFromArray = function (cx: PJSContext;
2859  var arr: PJSObject): PJSObject; cdecl;
2860var JS_NewInt16ArrayFromArray: TJS_NewInt16ArrayFromArray external SpiderMonkeyLib name 'SM_NewInt16ArrayFromArray';
2861
2862/// Create a new 16 bit unsigned integer typed array and copy in values
2863// from a given object
2864// - The object is used as if it was an array; that is, the new array (if
2865// successfully created) will have length given by array.length, and its
2866// elements will be those specified by array[0], array[1], and so on, after
2867// conversion to the typed array element type.
2868type TJS_NewUint16ArrayFromArray = function (cx: PJSContext;
2869  var arr: PJSObject): PJSObject; cdecl;
2870var JS_NewUint16ArrayFromArray: TJS_NewUint16ArrayFromArray external SpiderMonkeyLib name 'SM_NewUint16ArrayFromArray';
2871
2872/// Create a new 32 bit signed integer typed array and copy in values
2873// from a given object
2874// - The object is used as if it was an array; that is, the new array (if
2875// successfully created) will have length given by array.length, and its
2876// elements will be those specified by array[0], array[1], and so on, after
2877// conversion to the typed array element type.
2878type TJS_NewInt32ArrayFromArray = function (cx: PJSContext;
2879  var arr: PJSObject): PJSObject; cdecl;
2880var JS_NewInt32ArrayFromArray: TJS_NewInt32ArrayFromArray external SpiderMonkeyLib name 'SM_NewInt32ArrayFromArray';
2881
2882/// Create a new 32 bit unsigned integer typed array and copy in values
2883// from a given object
2884// - The object is used as if it was an array; that is, the new array (if
2885// successfully created) will have length given by array.length, and its
2886// elements will be those specified by array[0], array[1], and so on, after
2887// conversion to the typed array element type.
2888type TJS_NewUint32ArrayFromArray = function (cx: PJSContext;
2889  var arr: PJSObject): PJSObject; cdecl;
2890var JS_NewUint32ArrayFromArray: TJS_NewUint32ArrayFromArray external SpiderMonkeyLib name 'SM_NewUint32ArrayFromArray';
2891
2892/// Create a new 32 bit float (single) typed array and copy in values
2893// from a given object
2894// - The object is used as if it was an array; that is, the new array (if
2895// successfully created) will have length given by array.length, and its
2896// elements will be those specified by array[0], array[1], and so on, after
2897// conversion to the typed array element type.
2898type TJS_NewFloat32ArrayFromArray = function (cx: PJSContext;
2899  var arr: PJSObject): PJSObject; cdecl;
2900var JS_NewFloat32ArrayFromArray: TJS_NewFloat32ArrayFromArray external SpiderMonkeyLib name 'SM_NewFloat32ArrayFromArray';
2901
2902/// Create a new 64 bit float (double) typed array and copy in values
2903// from a given object
2904// - The object is used as if it was an array; that is, the new array (if
2905// successfully created) will have length given by array.length, and its
2906// elements will be those specified by array[0], array[1], and so on, after
2907// conversion to the typed array element type.
2908type TJS_NewFloat64ArrayFromArray = function (cx: PJSContext;
2909  var arr: PJSObject): PJSObject; cdecl;
2910var JS_NewFloat64ArrayFromArray: TJS_NewFloat64ArrayFromArray external SpiderMonkeyLib name 'SM_NewFloat64ArrayFromArray';
2911
2912/// Create a new 8 bit signed integer typed array using the given
2913// ArrayBuffer for storage
2914// - The length value is optional; if -1 is passed, enough elements to use up the
2915// remainder of the byte array is used as the default value
2916type TJS_NewInt8ArrayWithBuffer = function (cx: PJSContext;
2917  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2918var JS_NewInt8ArrayWithBuffer: TJS_NewInt8ArrayWithBuffer external SpiderMonkeyLib name 'SM_NewInt8ArrayWithBuffer';
2919
2920/// Create a new 8 bit unsigned integer typed array using the given
2921// ArrayBuffer for storage
2922// - The length value is optional; if -1 is passed, enough elements to use up the
2923// remainder of the byte array is used as the default value
2924type TJS_NewUint8ArrayWithBuffer = function (cx: PJSContext;
2925  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2926var JS_NewUint8ArrayWithBuffer: TJS_NewUint8ArrayWithBuffer external SpiderMonkeyLib name 'SM_NewUint8ArrayWithBuffer';
2927
2928/// Create a new 8 bit unsigned integer typed array using the given
2929// ArrayBuffer for storage
2930// - The length value is optional; if -1 is passed, enough elements to use up the
2931// remainder of the byte array is used as the default value
2932type TJS_NewUint8ClampedArrayWithBuffer = function (cx: PJSContext;
2933  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2934var JS_NewUint8ClampedArrayWithBuffer: TJS_NewUint8ClampedArrayWithBuffer external SpiderMonkeyLib name 'SM_NewUint8ClampedArrayWithBuffer';
2935
2936/// Create a new 16 bit signed integer typed array using the given
2937// ArrayBuffer for storage
2938// - The length value is optional; if -1 is passed, enough elements to use up the
2939// remainder of the byte array is used as the default value
2940type TJS_NewInt16ArrayWithBuffer = function (cx: PJSContext;
2941  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2942var JS_NewInt16ArrayWithBuffer: TJS_NewInt16ArrayWithBuffer external SpiderMonkeyLib name 'SM_NewInt16ArrayWithBuffer';
2943
2944/// Create a new 16 bit unsigned integer typed array using the given
2945// ArrayBuffer for storage
2946// - The length value is optional; if -1 is passed, enough elements to use up the
2947// remainder of the byte array is used as the default value
2948type TJS_NewUint16ArrayWithBuffer = function (cx: PJSContext;
2949  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2950var JS_NewUint16ArrayWithBuffer: TJS_NewUint16ArrayWithBuffer external SpiderMonkeyLib name 'SM_NewUint16ArrayWithBuffer';
2951
2952/// Create a new 32 bit signed integer typed array using the given
2953// ArrayBuffer for storage
2954// - The length value is optional; if -1 is passed, enough elements to use up the
2955// remainder of the byte array is used as the default value
2956type TJS_NewInt32ArrayWithBuffer = function (cx: PJSContext;
2957  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2958var JS_NewInt32ArrayWithBuffer: TJS_NewInt32ArrayWithBuffer external SpiderMonkeyLib name 'SM_NewInt32ArrayWithBuffer';
2959
2960/// Create a new 32 bit unsigned integer typed array using the given
2961// ArrayBuffer for storage
2962// - The length value is optional; if -1 is passed, enough elements to use up the
2963// remainder of the byte array is used as the default value
2964type TJS_NewUint32ArrayWithBuffer = function (cx: PJSContext;
2965  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2966var JS_NewUint32ArrayWithBuffer: TJS_NewUint32ArrayWithBuffer external SpiderMonkeyLib name 'SM_NewUint32ArrayWithBuffer';
2967
2968/// Create a new 32 bit float (single) typed array using the given
2969// ArrayBuffer for storage
2970// - The length value is optional; if -1 is passed, enough elements to use up the
2971// remainder of the byte array is used as the default value
2972type TJS_NewFloat32ArrayWithBuffer = function (cx: PJSContext;
2973  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2974var JS_NewFloat32ArrayWithBuffer: TJS_NewFloat32ArrayWithBuffer external SpiderMonkeyLib name 'SM_NewFloat32ArrayWithBuffer';
2975
2976/// Create a new 64 bit float (double) typed array using the given
2977// ArrayBuffer for storage
2978// - The length value is optional; if -1 is passed, enough elements to use up the
2979// remainder of the byte array is used as the default value
2980type TJS_NewFloat64ArrayWithBuffer = function (cx: PJSContext;
2981  var arrayBuffer: PJSObject; byteOffset: uint32; length: int32): PJSObject; cdecl;
2982var JS_NewFloat64ArrayWithBuffer: TJS_NewFloat64ArrayWithBuffer external SpiderMonkeyLib name 'SM_NewFloat64ArrayWithBuffer';
2983
2984/// Create a new SharedArrayBuffer with the given byte length.
2985type TJS_NewSharedArrayBuffer = function (cx: PJSContext;
2986  nbytes: uint32): PJSObject; cdecl;
2987var JS_NewSharedArrayBuffer: TJS_NewSharedArrayBuffer external SpiderMonkeyLib name 'SM_NewSharedArrayBuffer';
2988
2989/// Create a new ArrayBuffer with the given byte length.
2990type TJS_NewArrayBuffer = function (cx: PJSContext;
2991  nbytes: uint32): PJSObject; cdecl;
2992var JS_NewArrayBuffer: TJS_NewArrayBuffer external SpiderMonkeyLib name 'SM_NewArrayBuffer';
2993
2994/// Check whether obj supports JS_GetTypedArray* APIs
2995// - Note that this may return false if a security wrapper is encountered that
2996// denies the unwrapping.
2997// - if this test or one of the JS_Is*Array tests succeeds, then it is safe to call
2998// the dedicated accessor JSAPI calls
2999type TJS_IsTypedArrayObject = function (obj: PJSObject): Boolean; cdecl;
3000var JS_IsTypedArrayObject: TJS_IsTypedArrayObject external SpiderMonkeyLib name 'SM_IsTypedArrayObject';
3001
3002/// Check whether obj supports JS_GetArrayBufferView* APIs
3003// - Note that this may return false if a security wrapper is encountered that
3004// denies the unwrapping.
3005// - if this test or one of the JS_Is*Array tests succeeds, then it is safe to call
3006// the dedicated ArrayBufferView accessor JSAPI calls
3007type TJS_IsArrayBufferViewObject = function (obj: PJSObject): Boolean; cdecl;
3008var JS_IsArrayBufferViewObject: TJS_IsArrayBufferViewObject external SpiderMonkeyLib name 'SM_IsArrayBufferViewObject';
3009
3010/// Test for specific 8 bit signed integer typed array types (ArrayBufferView subtypes)
3011type TJS_IsInt8Array = function (obj: PJSObject): Boolean; cdecl;
3012var JS_IsInt8Array: TJS_IsInt8Array external SpiderMonkeyLib name 'SM_IsInt8Array';
3013
3014/// Test for specific 8 bit unsigned integer typed array types (ArrayBufferView subtypes)
3015type TJS_IsUint8Array = function (obj: PJSObject): Boolean; cdecl;
3016var JS_IsUint8Array: TJS_IsUint8Array external SpiderMonkeyLib name 'SM_IsUint8Array';
3017
3018/// Test for specific 8 bit unsigned integer typed array types (ArrayBufferView subtypes)
3019type TJS_IsUint8ClampedArray = function (obj: PJSObject): Boolean; cdecl;
3020var JS_IsUint8ClampedArray: TJS_IsUint8ClampedArray external SpiderMonkeyLib name 'SM_IsUint8ClampedArray';
3021
3022/// Test for specific 16 bit signed integer typed array types (ArrayBufferView subtypes)
3023type TJS_IsInt16Array = function (obj: PJSObject): Boolean; cdecl;
3024var JS_IsInt16Array: TJS_IsInt16Array external SpiderMonkeyLib name 'SM_IsInt16Array';
3025
3026/// Test for specific 16 bit unsigned integer typed array types (ArrayBufferView subtypes)
3027type TJS_IsUint16Array = function (obj: PJSObject): Boolean; cdecl;
3028var JS_IsUint16Array: TJS_IsUint16Array external SpiderMonkeyLib name 'SM_IsUint16Array';
3029
3030/// Test for specific 32 bit signed integer typed array types (ArrayBufferView subtypes)
3031type TJS_IsInt32Array = function (obj: PJSObject): Boolean; cdecl;
3032var JS_IsInt32Array: TJS_IsInt32Array external SpiderMonkeyLib name 'SM_IsInt32Array';
3033
3034/// Test for specific 32 bit unsigned integer typed array types (ArrayBufferView subtypes)
3035type TJS_IsUint32Array = function (obj: PJSObject): Boolean; cdecl;
3036var JS_IsUint32Array: TJS_IsUint32Array external SpiderMonkeyLib name 'SM_IsUint32Array';
3037
3038/// Test for specific 32 bit float (single) typed array types (ArrayBufferView subtypes)
3039type TJS_IsFloat32Array = function (obj: PJSObject): Boolean; cdecl;
3040var JS_IsFloat32Array: TJS_IsFloat32Array external SpiderMonkeyLib name 'SM_IsFloat32Array';
3041
3042/// Test for specific 64 bit float (double) typed array types (ArrayBufferView subtypes)
3043type TJS_IsFloat64Array = function (obj: PJSObject): Boolean; cdecl;
3044var JS_IsFloat64Array: TJS_IsFloat64Array external SpiderMonkeyLib name 'SM_IsFloat64Array';
3045
3046/// Return the isShared flag of a typed array, which denotes whether
3047// the underlying buffer is a SharedArrayBuffer.
3048//
3049// |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
3050// be known that it would pass such a test: it is a typed array or a wrapper of
3051// a typed array, and the unwrapping will succeed.
3052type TJS_GetTypedArraySharedness = function (obj: PJSObject): Boolean; cdecl;
3053var JS_GetTypedArraySharedness: TJS_GetTypedArraySharedness external SpiderMonkeyLib name 'SM_GetTypedArraySharedness';
3054
3055/// Unwrap 8 bit signed integer typed array into direct memory buffer
3056// - Return nil without throwing any exception if the object cannot be viewed as the
3057// correct typed array, or the typed array object on success, filling both out parameters
3058type TJS_GetObjectAsInt8Array = function (obj: PJSObject; out length: uint32;
3059  out isSharedMemory:Boolean; out Data: Pint8Vector): PJSObject; cdecl;
3060var JS_GetObjectAsInt8Array: TJS_GetObjectAsInt8Array external SpiderMonkeyLib name 'SM_GetObjectAsInt8Array';
3061
3062/// Unwrap 8 bit unsigned integer typed array into direct memory buffer
3063// - Return nil without throwing any exception if the object cannot be viewed as the
3064// correct typed array, or the typed array object on success, filling both out parameters
3065type TJS_GetObjectAsUint8Array = function (obj: PJSObject; out length: uint32;
3066  out isSharedMemory:Boolean; out  Data: Puint8Vector): PJSObject; cdecl;
3067var JS_GetObjectAsUint8Array: TJS_GetObjectAsUint8Array external SpiderMonkeyLib name 'SM_GetObjectAsUint8Array';
3068
3069/// Unwrap 8 bit unsigned integer typed array into direct memory buffer
3070// - Return nil without throwing any exception if the object cannot be viewed as the
3071// correct typed array, or the typed array object on success, filling both out parameters
3072type TJS_GetObjectAsUint8ClampedArray = function (obj: PJSObject;
3073  out length: uint32; out isSharedMemory:Boolean;
3074  out  Data: Puint8Vector): PJSObject; cdecl;
3075var JS_GetObjectAsUint8ClampedArray: TJS_GetObjectAsUint8ClampedArray external SpiderMonkeyLib name 'SM_GetObjectAsUint8ClampedArray';
3076
3077/// Unwrap 16 bit signed integer typed array into direct memory buffer
3078// - Return nil without throwing any exception if the object cannot be viewed as the
3079// correct typed array, or the typed array object on success, filling both out parameters
3080type TJS_GetObjectAsInt16Array = function (obj: PJSObject;
3081  out length: uint32; out isSharedMemory:Boolean;
3082  out  Data: Pint16Vector): PJSObject; cdecl;
3083var JS_GetObjectAsInt16Array: TJS_GetObjectAsInt16Array external SpiderMonkeyLib name 'SM_GetObjectAsInt16Array';
3084
3085/// Unwrap 16 bit unsigned integer typed array into direct memory buffer
3086// - Return nil without throwing any exception if the object cannot be viewed as the
3087// correct typed array, or the typed array object on success, filling both out parameters
3088type TJS_GetObjectAsUint16Array = function (obj: PJSObject; out length: uint32;
3089  out isSharedMemory:Boolean; out  Data: Puint16Vector): PJSObject; cdecl;
3090var JS_GetObjectAsUint16Array: TJS_GetObjectAsUint16Array external SpiderMonkeyLib name 'SM_GetObjectAsUint16Array';
3091
3092/// Unwrap 32 bit signed integer typed array into direct memory buffer
3093// - Return nil without throwing any exception if the object cannot be viewed as the
3094// correct typed array, or the typed array object on success, filling both out parameters
3095type TJS_GetObjectAsInt32Array = function (obj: PJSObject; out length: uint32;
3096  out isSharedMemory:Boolean; out  Data: Pint32Vector): PJSObject; cdecl;
3097var JS_GetObjectAsInt32Array: TJS_GetObjectAsInt32Array external SpiderMonkeyLib name 'SM_GetObjectAsInt32Array';
3098
3099/// Unwrap 32 bit unsigned integer typed array into direct memory buffer
3100// - Return nil without throwing any exception if the object cannot be viewed as the
3101// correct typed array, or the typed array object on success, filling both out parameters
3102type TJS_GetObjectAsUint32Array = function (obj: PJSObject; out length: uint32;
3103  out isSharedMemory:Boolean; out  Data: Puint32Vector): PJSObject; cdecl;
3104var JS_GetObjectAsUint32Array: TJS_GetObjectAsUint32Array external SpiderMonkeyLib name 'SM_GetObjectAsUint32Array';
3105
3106/// Unwrap 32 bit float (single) typed array into direct memory buffer
3107// - Return nil without throwing any exception if the object cannot be viewed as the
3108// correct typed array, or the typed array object on success, filling both out parameters
3109type TJS_GetObjectAsFloat32Array = function (obj: PJSObject; out length: uint32;
3110  out isSharedMemory:Boolean; out  Data: Pfloat32Vector): PJSObject; cdecl;
3111var JS_GetObjectAsFloat32Array: TJS_GetObjectAsFloat32Array external SpiderMonkeyLib name 'SM_GetObjectAsFloat32Array';
3112
3113/// Unwrap 64 bit float (double) typed array into direct memory buffer
3114// - Return nil without throwing any exception if the object cannot be viewed as the
3115// correct typed array, or the typed array object on success, filling both out parameters
3116type TJS_GetObjectAsFloat64Array = function (obj: PJSObject; out length: uint32;
3117  out isSharedMemory:Boolean; out  Data: Pfloat64Vector): PJSObject; cdecl;
3118var JS_GetObjectAsFloat64Array: TJS_GetObjectAsFloat64Array external SpiderMonkeyLib name 'SM_GetObjectAsFloat64Array';
3119
3120/// Unwrap an object as its raw binary memory buffer
3121// - Return nil without throwing any exception if the object cannot be viewed as the
3122// correct typed array, or the typed array object on success, filling both out parameters
3123type TJS_GetObjectAsArrayBufferView = function (obj: PJSObject;
3124  out length: uint32; out isSharedMemory:Boolean;
3125  out  Data: Puint8Vector): PJSObject; cdecl;
3126var JS_GetObjectAsArrayBufferView: TJS_GetObjectAsArrayBufferView external SpiderMonkeyLib name 'SM_GetObjectAsArrayBufferView';
3127
3128/// Unwrap an object as its raw binary memory buffer
3129// - Return nil without throwing any exception if the object cannot be viewed as the
3130// correct typed array, or the typed array object on success, filling both out parameters
3131type TJS_GetObjectAsArrayBuffer = function (obj: PJSObject; out length: uint32;
3132  out Data: Puint8Vector): PJSObject; cdecl;
3133var JS_GetObjectAsArrayBuffer: TJS_GetObjectAsArrayBuffer external SpiderMonkeyLib name 'SM_GetObjectAsArrayBuffer';
3134
3135  /// Get the type of elements in a typed array, or jsabTYPE_DATAVIEW if a DataView
3136type TJS_GetArrayBufferViewType = function (
3137  obj: PJSObject): JSArrayBufferViewType; cdecl;
3138var JS_GetArrayBufferViewType: TJS_GetArrayBufferViewType external SpiderMonkeyLib name 'SM_GetArrayBufferViewType';
3139
3140/// Check whether obj supports the JS_GetArrayBuffer* APIs
3141// - Note that this may return false if a security wrapper is encountered that denies the
3142// unwrapping
3143// - If this test succeeds, then it is safe to call the various accessor JSAPI calls
3144type TJS_IsArrayBufferObject = function (obj: PJSObject): Boolean; cdecl;
3145var JS_IsArrayBufferObject: TJS_IsArrayBufferObject external SpiderMonkeyLib name 'SM_IsArrayBufferObject';
3146
3147type TJS_IsSharedArrayBufferObject = function (obj: PJSObject): Boolean; cdecl;
3148var JS_IsSharedArrayBufferObject: TJS_IsSharedArrayBufferObject external SpiderMonkeyLib name 'SM_IsSharedArrayBufferObject';
3149
3150/// Return the available byte length of an array buffer
3151// - obj must have passed a JS_IsArrayBufferObject test, or somehow be known
3152// that it would pass such a test: it is an ArrayBuffer or a wrapper of an
3153// ArrayBuffer, and the unwrapping will succeed
3154type TJS_GetArrayBufferByteLength = function (obj: PJSObject): uint32; cdecl;
3155var JS_GetArrayBufferByteLength: TJS_GetArrayBufferByteLength external SpiderMonkeyLib name 'SM_GetArrayBufferByteLength';
3156
3157type TJS_GetSharedArrayBufferByteLength = function (
3158  obj: PJSObject): uint32; cdecl;
3159var JS_GetSharedArrayBufferByteLength: TJS_GetSharedArrayBufferByteLength external SpiderMonkeyLib name 'SM_GetSharedArrayBufferByteLength';
3160
3161/// Return true if the arrayBuffer contains any data. This will return false for
3162// ArrayBuffer.prototype and neutered ArrayBuffers.
3163//
3164// |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
3165// that it would pass such a test: it is an ArrayBuffer or a wrapper of an
3166// ArrayBuffer, and the unwrapping will succeed.
3167type TJS_ArrayBufferHasData = function (obj: PJSObject): Boolean; cdecl;
3168var JS_ArrayBufferHasData: TJS_ArrayBufferHasData external SpiderMonkeyLib name 'SM_ArrayBufferHasData';
3169
3170/// Return a pointer to an array buffer's data
3171// - The buffer is still owned by the array buffer object, and should not
3172// be modified on another thread. The returned pointer is stable across GCs
3173// - obj must have passed a JS_IsArrayBufferObject test, or somehow be known
3174// that it would pass such a test: it is an ArrayBuffer or a wrapper of an
3175// ArrayBuffer, and the unwrapping will succeed.
3176type TJS_GetArrayBufferData = function (obj: PJSObject;
3177  out isSharedMemory: Boolean;
3178  nogc: PJSAutoCheckCannotGC{Not used in SM code}): Puint8Vector; cdecl;
3179var JS_GetArrayBufferData: TJS_GetArrayBufferData external SpiderMonkeyLib name 'SM_GetArrayBufferData';
3180
3181/// Check whether the obj is ArrayBufferObject and memory mapped. Note that this
3182// may return false if a security wrapper is encountered that denies the
3183// unwrapping.
3184type TJS_IsMappedArrayBufferObject = function (obj: PJSObject): Boolean; cdecl;
3185var JS_IsMappedArrayBufferObject: TJS_IsMappedArrayBufferObject external SpiderMonkeyLib name 'SM_IsMappedArrayBufferObject';
3186
3187/// Return the number of elements in a typed array
3188// - obj must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
3189// be known that it would pass such a test: it is a typed array or a wrapper of
3190// a typed array, and the unwrapping will succeed.
3191type TJS_GetTypedArrayLength = function (obj: PJSObject): uint32; cdecl;
3192var JS_GetTypedArrayLength: TJS_GetTypedArrayLength external SpiderMonkeyLib name 'SM_GetTypedArrayLength';
3193
3194/// Return the byte offset from the start of an array buffer to the start of a
3195// typed array view
3196// - obj must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
3197// be known that it would pass such a test: it is a typed array or a wrapper of
3198// a typed array, and the unwrapping will succeed.
3199type TJS_GetTypedArrayByteOffset = function (obj: PJSObject): uint32; cdecl;
3200var JS_GetTypedArrayByteOffset: TJS_GetTypedArrayByteOffset external SpiderMonkeyLib name 'SM_GetTypedArrayByteOffset';
3201
3202/// Return the byte length of a typed array
3203// - obj must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
3204// be known that it would pass such a test: it is a typed array or a wrapper of
3205// a typed array, and the unwrapping will succeed
3206type TJS_GetTypedArrayByteLength = function (obj: PJSObject): uint32; cdecl;
3207var JS_GetTypedArrayByteLength: TJS_GetTypedArrayByteLength external SpiderMonkeyLib name 'SM_GetTypedArrayByteLength';
3208
3209/// More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
3210type TJS_GetArrayBufferViewByteLength = function (obj: PJSObject): uint32; cdecl;
3211var JS_GetArrayBufferViewByteLength: TJS_GetArrayBufferViewByteLength external SpiderMonkeyLib name 'SM_GetArrayBufferViewByteLength';
3212
3213/// Return a pointer to the start of the data referenced by a typed 8 bit signed integer array
3214// - The data is still owned by the typed array, and should not be modified on
3215// another thread
3216// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3217// pass such a test: it is a typed array or a wrapper of a typed array, and the
3218// unwrapping will succeed
3219type TJS_GetInt8ArrayData = function (obj: PJSObject;
3220  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pint8Vector; cdecl;
3221var JS_GetInt8ArrayData: TJS_GetInt8ArrayData external SpiderMonkeyLib name 'SM_GetInt8ArrayData';
3222
3223/// Return a pointer to the start of the data referenced by a typed 8 bit unsigned integer array
3224// - The data is still owned by the typed array, and should not be modified on
3225// another thread
3226// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3227// pass such a test: it is a typed array or a wrapper of a typed array, and the
3228// unwrapping will succeed
3229type TJS_GetUint8ArrayData = function (obj: PJSObject;
3230  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint8Vector; cdecl;
3231var JS_GetUint8ArrayData: TJS_GetUint8ArrayData external SpiderMonkeyLib name 'SM_GetUint8ArrayData';
3232
3233/// Return a pointer to the start of the data referenced by a typed 8 bit unsigned integer array
3234// - The data is still owned by the typed array, and should not be modified on
3235// another thread
3236// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3237// pass such a test: it is a typed array or a wrapper of a typed array, and the
3238// unwrapping will succeed
3239type TJS_GetUint8ClampedArrayData = function (obj: PJSObject;
3240  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint8Vector; cdecl;
3241var JS_GetUint8ClampedArrayData: TJS_GetUint8ClampedArrayData external SpiderMonkeyLib name 'SM_GetUint8ClampedArrayData';
3242
3243/// Return a pointer to the start of the data referenced by a typed 16 bit signed integer array
3244// - The data is still owned by the typed array, and should not be modified on
3245// another thread
3246// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3247// pass such a test: it is a typed array or a wrapper of a typed array, and the
3248// unwrapping will succeed
3249type TJS_GetInt16ArrayData = function (obj: PJSObject;
3250  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pint16Vector; cdecl;
3251var JS_GetInt16ArrayData: TJS_GetInt16ArrayData external SpiderMonkeyLib name 'SM_GetInt16ArrayData';
3252
3253/// Return a pointer to the start of the data referenced by a typed 16 bit unsigned integer array
3254// - The data is still owned by the typed array, and should not be modified on
3255// another thread
3256// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3257// pass such a test: it is a typed array or a wrapper of a typed array, and the
3258// unwrapping will succeed
3259type TJS_GetUint16ArrayData = function (obj: PJSObject;
3260  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint16Vector; cdecl;
3261var JS_GetUint16ArrayData: TJS_GetUint16ArrayData external SpiderMonkeyLib name 'SM_GetUint16ArrayData';
3262
3263/// Return a pointer to the start of the data referenced by a typed 32 bit signed integer array
3264// - The data is still owned by the typed array, and should not be modified on
3265// another thread
3266// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3267// pass such a test: it is a typed array or a wrapper of a typed array, and the
3268// unwrapping will succeed
3269type TJS_GetInt32ArrayData = function (obj: PJSObject;
3270  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pint32Vector; cdecl;
3271var JS_GetInt32ArrayData: TJS_GetInt32ArrayData external SpiderMonkeyLib name 'SM_GetInt32ArrayData';
3272
3273/// Return a pointer to the start of the data referenced by a typed 32 bit unsigned integer array
3274// - The data is still owned by the typed array, and should not be modified on
3275// another thread
3276// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3277// pass such a test: it is a typed array or a wrapper of a typed array, and the
3278// unwrapping will succeed
3279type TJS_GetUint32ArrayData = function (obj: PJSObject;
3280  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Puint32Vector; cdecl;
3281var JS_GetUint32ArrayData: TJS_GetUint32ArrayData external SpiderMonkeyLib name 'SM_GetUint32ArrayData';
3282
3283/// Return a pointer to the start of the data referenced by a typed 32 bit float (single) array
3284// - The data is still owned by the typed array, and should not be modified on
3285// another thread
3286// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3287// pass such a test: it is a typed array or a wrapper of a typed array, and the
3288// unwrapping will succeed
3289type TJS_GetFloat32ArrayData = function (obj: PJSObject;
3290  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pfloat32Vector; cdecl;
3291var JS_GetFloat32ArrayData: TJS_GetFloat32ArrayData external SpiderMonkeyLib name 'SM_GetFloat32ArrayData';
3292
3293/// Return a pointer to the start of the data referenced by a typed 64 bit float (double) array
3294// - The data is still owned by the typed array, and should not be modified on
3295// another thread
3296// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3297// pass such a test: it is a typed array or a wrapper of a typed array, and the
3298// unwrapping will succeed
3299type TJS_GetFloat64ArrayData = function (obj: PJSObject;
3300  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pfloat64Vector; cdecl;
3301var JS_GetFloat64ArrayData: TJS_GetFloat64ArrayData external SpiderMonkeyLib name 'SM_GetFloat64ArrayData';
3302
3303/// Return a pointer to the start of the data referenced by any typed array
3304// - The data is still owned by the typed array, and should not be modified on
3305// another thread
3306// - obj must have passed a JS_Is*Array test, or somehow be known that it would
3307// pass such a test: it is a typed array or a wrapper of a typed array, and the
3308// unwrapping will succeed
3309// - Prefer the type-specific versions when possible
3310type TJS_GetArrayBufferViewData = function (obj: PJSObject;
3311  out isSharedMemory: Boolean; nogc: PJSAutoCheckCannotGC): Pointer; cdecl;
3312var JS_GetArrayBufferViewData: TJS_GetArrayBufferViewData external SpiderMonkeyLib name 'SM_GetArrayBufferViewData';
3313
3314/// Return the ArrayBuffer underlying an ArrayBufferView
3315// - If the buffer has been neutered, this will still return the neutered buffer.
3316// - obj must be an object that would return true for JS_IsArrayBufferViewObject()
3317type TJS_GetArrayBufferViewBuffer = function (cx: PJSContext;
3318  var obj: PJSObject; out isSharedMemory: Boolean): PJSObject; cdecl;
3319var JS_GetArrayBufferViewBuffer: TJS_GetArrayBufferViewBuffer external SpiderMonkeyLib name 'SM_GetArrayBufferViewBuffer';
3320
3321////modules
3322
3323/// Initialize modeles classes next 2 functions cannot work without calling this function                !!! EMPTY !!!
3324function JS_InitModuleClasses(cx: PJSContext; var obj: PJSObject): boolean; cdecl; external SpiderMonkeyLib name 'SM_InitModuleClasses';
3325
3326/// Compile script as module
3327function JS_CompileModule(cx: PJSContext;
3328   var obj: PJSObject;
3329   options: PJSCompileOptions;
3330   chars: PCChar16; length: size_t): PJSObject; cdecl; external SpiderMonkeyLib name 'SM_CompileModule';
3331
3332/// Set handler for module resolving
3333type TJS_SetModuleResolveHook = procedure (cx: PJSContext; var hook: PJSFunction); cdecl;
3334var JS_SetModuleResolveHook: TJS_SetModuleResolveHook external SpiderMonkeyLib name 'SM_SetModuleResolveHook';
3335
3336type
3337  pjsval = ^jsval;
3338
3339var
3340  /// global TSynAnsiConvert instance to handle LATIN1(ISO/IEC 8859-1) encoding
3341  // - this instance is global and instantied during the whole program life time
3342  // - Spidermonkey internal encoding is LATIN1 or UTF-16
3343  Latin1AnsiConvert: TSynAnsiConvert;
3344
3345implementation
3346
3347uses
3348  Variants;
3349
3350const
3351  JSVAL_INT_MAX = int32($7fffffff);
3352
3353procedure JSError(cx: PJSContext; aException: Exception);
3354var
3355  ws: WideString;
3356begin
3357  if not JS_IsExceptionPending(cx) then
3358    // raise only if this is the first exception in chain
3359    if aException is EOutOfMemory then
3360      JS_ReportOutOfMemory(cx)
3361    else if aException is ESMRangeException then begin
3362      ws := StringToSynUnicode(aException.Message);
3363      JSRangeErrorUC(cx, ws);
3364    end else if aException is ESMTypeException then begin
3365      ws := StringToSynUnicode(aException.Message);
3366      JSTypeErrorUC(cx, ws);
3367    end else begin
3368      ws := StringToSynUnicode(aException.Message);
3369      JSErrorUC(cx, ws, aException.HelpContext);
3370    end;
3371end;
3372
3373const
3374 ErrorUCFormatString: JSErrorFormatString =
3375  (
3376    name: 'Error';
3377    format: '{0}';
3378    argCount: 1;
3379    exnType: JSEXN_ERR;
3380  );
3381 RangeErrorUCFormatString: JSErrorFormatString =
3382  (
3383    name: 'RangeError';
3384    format: '{0}';
3385    argCount: 1;
3386    exnType: JSEXN_RANGEERR;
3387  );
3388 TypeErrorUCFormatString: JSErrorFormatString =
3389  (
3390    name: 'TypeError';
3391    format: '{0}';
3392    argCount: 1;
3393    exnType: JSEXN_TYPEERR;
3394  );
3395  SMExceptionNumber = 500;//from 0 to JSErr_Limit(421 for SM 45 ) Error numbers are reserved
3396
3397function ReportErrorUC(userRef: Pointer; const errorNumber: uintN): PJSErrorFormatString; cdecl;
3398begin
3399  result := @ErrorUCFormatString;
3400end;
3401
3402function ReportRangeErrorUC(userRef: Pointer; const errorNumber: uintN): PJSErrorFormatString; cdecl;
3403begin
3404  result := @RangeErrorUCFormatString;
3405end;
3406
3407function TypeRangeErrorUC(userRef: Pointer; const errorNumber: uintN): PJSErrorFormatString; cdecl;
3408begin
3409  result := @TypeErrorUCFormatString;
3410end;
3411
3412procedure JSErrorUC(cx: PJSContext; aMessage: WideString; errorCode: integer);
3413begin
3414  if not JS_IsExceptionPending(cx) then
3415    JS_ReportErrorNumberUC(cx, ReportErrorUC, nil, SMExceptionNumber + errorCode, Pointer(aMessage));
3416end;
3417
3418procedure JSRangeErrorUC(cx: PJSContext; aMessage: WideString);
3419begin
3420  if not JS_IsExceptionPending(cx) then
3421    JS_ReportErrorNumberUC(cx, ReportRangeErrorUC, nil, SMExceptionNumber ,Pointer(aMessage));
3422end;
3423
3424procedure JSTypeErrorUC(cx: PJSContext; aMessage: WideString);
3425begin
3426  if not JS_IsExceptionPending(cx) then
3427    JS_ReportErrorNumberUC(cx, TypeRangeErrorUC, nil, SMExceptionNumber ,Pointer(aMessage));
3428end;
3429
3430function InitJS: Boolean;
3431begin
3432  // remove extra threads + allow GS to finalize native objects;
3433  // See for details the same issue in modgoDB:
3434  // https://jira.mongodb.org/browse/SERVER-21728
3435  JS_DisableExtraThreads();
3436  Result := JS_Init;
3437end;
3438
3439procedure ShutDownJS;
3440begin
3441  JS_ShutDown;
3442end;
3443
3444{ JSCompileOptions }
3445
3446procedure JSCompileOptions.SetFileLineAndUtf8(const fn: RawUTF8; l: cardinal;
3447  isUtf8: boolean);
3448begin
3449  JS_SetCompileOptionsFileLineAndUtf8(@Self, pointer(fn), l, isUtf8);
3450end;
3451
3452{ JSString }
3453
3454procedure JSString.ToJSONString(cx: PJSContext; W: TTextWriter);
3455var
3456  str8: PCChar;
3457  str16: PCChar16;
3458  strL: size_t;
3459begin
3460  W.Add('"');
3461  if JS_StringHasLatin1Chars(@self) then begin
3462    str8 := JS_GetLatin1StringCharsAndLength(cx, @nullPtr, @self, @strL);
3463    W.AddJSONEscape(pointer(str8),strL);
3464  end else begin
3465    str16 := JS_GetTwoByteStringCharsAndLength(cx, @nullPtr, @self, @strL);
3466    W.AddJSONEscapeW(pointer(str16),strL);
3467  end;
3468  W.Add('"');
3469end;
3470
3471function JSString.ToJSVal: jsval;
3472begin
3473  Result.asJSString := @self
3474end;
3475
3476function JSString.ToString(cx: PJSContext): string;
3477var
3478  str8: PCChar;
3479  str16: PCChar16;
3480  strL: size_t;
3481begin
3482  if JS_StringHasLatin1Chars(@self) then begin
3483    str8 := JS_GetLatin1StringCharsAndLength(cx, @nullPtr, @self, @strL);
3484    {$ifdef UNICODE}
3485      Result := Latin1AnsiConvert.AnsiToUnicodeString(str8, strL);
3486    {$else}
3487      SetString(Result, str8, strL);
3488    {$endif}
3489  end else begin
3490    str16 := JS_GetTwoByteStringCharsAndLength(cx, @nullPtr, @self, @strL);
3491    RawUnicodeToString(PWideChar(str16),strL,result)
3492  end;
3493end;
3494
3495function JSString.ToSynUnicode(cx: PJSContext): SynUnicode;
3496var
3497  str8: PCChar;
3498  str16: PCChar16;
3499  strL: size_t;
3500begin
3501  if JS_StringHasLatin1Chars(@self) then begin
3502    str8 := JS_GetLatin1StringCharsAndLength(cx, @nullPtr, @self, @strL);
3503    Result := Latin1AnsiConvert.AnsiToUnicodeString(str8, strL);
3504  end else begin
3505    str16 := JS_GetTwoByteStringCharsAndLength(cx, @nullPtr, @self, @strL);
3506    SetString(Result, str16, strL);
3507  end;
3508end;
3509
3510function JSString.ToUTF8(cx: PJSContext): RawUTF8;
3511begin
3512  ToUTF8(cx,result);
3513end;
3514
3515procedure JSString.ToUTF8(cx: PJSContext; out result: RawUTF8);
3516var
3517  str8: PCChar;
3518  str16: PCChar16;
3519  strL: size_t;
3520begin
3521  if JS_StringHasLatin1Chars(@self) then begin
3522    str8 := JS_GetLatin1StringCharsAndLength(cx, @nullPtr, @self, @strL);
3523    result := Latin1AnsiConvert.AnsiBufferToRawUTF8(str8, strL);
3524  end else begin
3525    str16 := JS_GetTwoByteStringCharsAndLength(cx, @nullPtr, @self, @strL);
3526    RawUnicodeToUTF8(str16,strL,result, [ccfNoTrailingZero, ccfReplacementCharacterForUnmatchedSurrogate]);
3527  end;
3528end;
3529
3530function JSString.ToAnsi(cx: PJSContext): AnsiString;
3531var
3532  str8: PCChar;
3533  str16: PCChar16;
3534  strL: size_t;
3535begin
3536  if JS_StringHasLatin1Chars(@self) then begin
3537    str8 := JS_GetLatin1StringCharsAndLength(cx, @nullPtr, @self, @strL);
3538    SetLength(Result, strL);
3539    MoveFast(Pointer(str8)^,Result[1],strL);
3540  end else begin
3541    str16 := JS_GetTwoByteStringCharsAndLength(cx, @nullPtr, @self, @strL);
3542    Result := CurrentAnsiConvert.UnicodeBufferToAnsi(str16,strL);
3543  end;
3544end;
3545
3546procedure JSString.ToVariant(cx: PJSContext; var Value: Variant);
3547var
3548  str8: PCChar;
3549  str16: PCChar16;
3550  strL: size_t;
3551begin
3552  VarClear(Value);
3553  with TVarData(Value) do begin
3554    VType := varSynUnicode;
3555    VAny := nil; // avoid GPF below
3556    if JS_StringHasLatin1Chars(@self) then begin
3557      str8 := JS_GetLatin1StringCharsAndLength(cx, @nullPtr, @self, @strL);
3558      SynUnicode(VAny) := Latin1AnsiConvert.AnsiToUnicodeString(str8, strL);
3559    end else begin
3560      str16 := JS_GetTwoByteStringCharsAndLength(cx, @nullPtr, @self, @strL);
3561      SetString(SynUnicode(VAny), str16, strL);
3562    end;
3563  end;
3564end;
3565
3566procedure JSString.ToUTF8(cx: PJSContext; W: TTextWriter);
3567var
3568  str8: PCChar;
3569  str16: PCChar16;
3570  strL: size_t;
3571  tmpU8: array[0..256*3] of AnsiChar;
3572  U8: PUTF8Char;
3573begin
3574  if JS_StringHasLatin1Chars(@self) then begin
3575    str8 := JS_GetLatin1StringCharsAndLength(cx, @nullPtr, @self, @strL);
3576
3577    if strL>=SizeOf(tmpU8)div 3 then
3578      Getmem(U8,strL*3+1) else
3579      U8 := @tmpU8;
3580    strL := Latin1AnsiConvert.AnsiBufferToUTF8(U8,pointer(str8),strL)-U8;
3581    W.AddNoJSONEscape(pointer(U8), strL);
3582    if U8<>@tmpU8 then
3583      FreeMem(U8);
3584  end else begin
3585    str16 := JS_GetTwoByteStringCharsAndLength(cx, @nullPtr, @self, @strL);
3586    W.AddNoJSONEscapeW(pointer(str16),strL);
3587  end;
3588end;
3589
3590function JSString.HasLatin1Chars: Boolean;
3591begin
3592  result := JS_StringHasLatin1Chars(@self);
3593end;
3594
3595function JSString.GetLatin1StringCharsAndLength(cx: PJSContext;
3596  out len: size_t): PCChar;
3597begin
3598  Result := JS_GetLatin1StringCharsAndLength(cx, @nullPtr, @Self, @len);
3599end;
3600
3601function JSString.Length: size_t;
3602begin
3603  Result := JS_GetStringLength(@self);
3604end;
3605
3606function JSString.GetTwoByteStringCharsAndLength(cx: PJSContext;
3607  out len: size_t): PCChar16;
3608begin
3609  Result := JS_GetTwoByteStringCharsAndLength(cx, @nullPtr, @Self, @len);
3610end;
3611
3612{ JSContext }
3613function JSContext.CheckForInterrupt: Boolean;
3614begin
3615  result := JS_CheckForInterrupt(@Self);
3616end;
3617
3618procedure JSContext.DisableInterruptCallback;
3619begin
3620  JS_DisableInterruptCallback(@self);
3621end;
3622
3623procedure JSContext.AddInterruptCallback(callback: JSInterruptCallback);
3624begin
3625  JS_AddInterruptCallback(@self, callback);
3626end;
3627
3628procedure JSContext.ResetInterruptCallback(disable: boolean);
3629begin
3630  JS_ResetInterruptCallback(@self, disable);
3631end;
3632
3633procedure JSContext.ClearPendingException;
3634begin
3635  JS_ClearPendingException(@self);
3636end;
3637
3638function JSContext.CurrentGlobalOrNull: PJSObject;
3639begin
3640  result := JS_CurrentGlobalOrNull(@self);
3641end;
3642
3643procedure JSContext.Destroy;
3644begin
3645  JS_DestroyContext(@self);
3646end;
3647
3648function JSContext.EnterCompartment(target: PJSObject): PJSCompartment;
3649begin
3650  Result := JS_EnterCompartment(@self, target);
3651end;
3652
3653function JSContext.GetPendingException(out rv: jsval): boolean;
3654begin
3655  Result := JS_GetPendingException(@self, rv);
3656end;
3657
3658function JSContext.GetPrivate: Pointer;
3659begin
3660  result := JS_GetContextPrivate(@self);
3661end;
3662
3663function JSContext.IdToValue(id: jsid; out v: jsval): Boolean;
3664begin
3665  Result := JS_IdToValue(@Self, id, v);
3666end;
3667
3668function JSContext.InitStandardClasses(var obj: PJSObject): boolean;
3669begin
3670  Result := JS_InitStandardClasses(@Self, obj);
3671end;
3672
3673procedure JSContext.SetModuleResolveHook(var hook: PJSFunction);
3674begin
3675  JS_SetModuleResolveHook(@Self, hook);
3676end;
3677
3678function JSContext.NewDateObjectMsec(msec: double): PJSObject;
3679begin
3680  Result := JS_NewDateObjectMsec(@Self, msec);
3681end;
3682
3683procedure JSContext.LeaveCompartment(oldCompartment: PJSCompartment);
3684begin
3685  JS_LeaveCompartment(@Self, oldCompartment);
3686end;
3687
3688procedure JSContext.MaybeGC;
3689begin
3690  JS_MaybeGC(@self);
3691end;
3692
3693function JSContext.NewDateObject(year, mon, mday, hour, min, sec: int32): PJSObject;
3694begin
3695  Result := JS_NewDateObject(@Self, year, mon, mday, hour, min, sec);
3696end;
3697
3698function JS_NewCompartmentOptions(): PJS_CompartmentOptions; cdecl;
3699  external SpiderMonkeyLib name 'SM_NewCompartmentOptions';
3700procedure JS_FreeCompartmentOptions(opt: PJS_CompartmentOptions); cdecl;
3701  external SpiderMonkeyLib name 'SM_FreeCompartmentOptions';
3702
3703function JSContext.NewGlobalObject(clasp: PJSClass; hookOption: OnNewGlobalHookOption): PJSObject;
3704var
3705  Opt: PJS_CompartmentOptions;
3706begin
3707  Opt := JS_NewCompartmentOptions;
3708  Result := JS_NewGlobalObject(@Self, clasp, nil, hookOption, Opt);
3709  JS_FreeCompartmentOptions(Opt);
3710end;
3711
3712function JSContext.NewInt16Array(nelements: uint32): PJSObject;
3713begin
3714  Result := JS_NewInt16Array(@Self, nelements);
3715end;
3716
3717function JSContext.NewInt16ArrayFromArray(var arr: PJSObject): PJSObject;
3718begin
3719  Result := JS_NewInt16ArrayFromArray(@Self, arr);
3720end;
3721
3722function JSContext.NewInt16ArrayWithBuffer(var arrayBuffer: PJSObject;
3723  byteOffset: uint32; length: int32): PJSObject;
3724begin
3725  Result := JS_NewInt16ArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
3726end;
3727
3728function JSContext.NewInt32Array(nelements: uint32): PJSObject;
3729begin
3730  Result := JS_NewInt32Array(@Self, nelements);
3731end;
3732
3733function JSContext.NewInt32ArrayFromArray(var arr: PJSObject): PJSObject;
3734begin
3735  Result := JS_NewInt32ArrayFromArray(@Self, arr);
3736end;
3737
3738function JSContext.NewInt32ArrayWithBuffer(var arrayBuffer: PJSObject;
3739  byteOffset: uint32; length: int32): PJSObject;
3740begin
3741  Result := JS_NewInt32ArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
3742end;
3743
3744function JSContext.NewInt8Array(nelements: uint32): PJSObject;
3745begin
3746  Result := JS_NewInt8Array(@Self, nelements);
3747end;
3748
3749function JSContext.NewInt8ArrayFromArray(var arr: PJSObject): PJSObject;
3750begin
3751  Result := JS_NewInt8ArrayFromArray(@Self, arr);
3752end;
3753
3754function JSContext.NewInt8ArrayWithBuffer(var arrayBuffer: PJSObject;
3755  byteOffset: uint32; length: int32): PJSObject;
3756begin
3757  Result := JS_NewInt8ArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
3758end;
3759
3760function JSContext.NewJSString(TextWide: PWideChar;
3761  TextLen: integer): PJSString;
3762begin
3763  result := JS_NewUCStringCopyN(@Self, pointer(TextWide), TextLen);
3764end;
3765
3766function JSContext.NewJSString(TextAnsi: PAnsiChar; TextLen,
3767  CodePage: integer): PJSString;
3768var short: array[byte] of CChar16; // to avoid temp allocation on heap
3769    buf: PCChar16;
3770begin
3771  if TextLen<(sizeof(short) div 3) then
3772    buf := @short else
3773    GetMem(buf,TextLen*3+2);
3774  result := JS_NewUCStringCopyN(@Self, buf,
3775    TSynAnsiConvert.Engine(CodePage).AnsiBufferToUnicode(PWideChar(buf),TextAnsi,TextLen)-buf);
3776  if buf<>@short then
3777    FreeMem(buf);
3778end;
3779
3780function JSContext.NewJSString(const Value: SynUnicode): PJSString;
3781begin
3782  result := JS_NewUCStringCopyN(@Self, pointer(Value), Length(Value));
3783end;
3784
3785function JSContext.NewObject(clasp: PJSClass): PJSObject;
3786begin
3787  Result := JS_NewObject(@Self, clasp);
3788end;
3789
3790function JSContext.NewObjectWithGivenProto(clasp: PJSClass; var proto: PJSObject): PJSObject;
3791begin
3792  Result := JS_NewObjectWithGivenProto(@Self, clasp, proto);
3793end;
3794
3795procedure JSContext.ReportError(format: PCChar);
3796begin
3797  JS_ReportError(@Self, format);
3798end;
3799
3800procedure JSContext.ReportErrorNumberUC(errorCallback: JSErrorCallback; userRef: pointer; const erroNubmer: uintN);
3801begin
3802  JS_ReportErrorNumberUC(@Self, errorCallback, userRef, erroNubmer);
3803end;
3804
3805procedure JSContext.ReportOutOfMemory;
3806begin
3807  JS_ReportOutOfMemory(@self);
3808end;
3809
3810procedure JSContext.SetPrivate(const Value: Pointer);
3811begin
3812  JS_SetContextPrivate(@self,Value);
3813end;
3814
3815function JSContext.TypeOfValue(v: jsval): JSType;
3816begin
3817  result := JS_TypeOfValue(@Self, v);
3818end;
3819
3820function JSContext.ValueToId(var v: jsval; out id: jsid): Boolean;
3821begin
3822  Result := JS_ValueToId(@Self, v, id);
3823end;
3824
3825function JSContext.WrapObject(var obj: PJSObject): boolean;
3826begin
3827  Result := JS_WrapObject(@Self, obj);
3828end;
3829
3830procedure JSContext.BeginRequest;
3831begin
3832  JS_BeginRequest(@self);
3833end;
3834
3835procedure JSContext.EndRequest;
3836begin
3837  JS_EndRequest(@self);
3838end;
3839
3840function JSContext.GetArrayBufferViewBuffer(var obj: PJSObject;
3841  out isSharedMemory: Boolean): PJSObject;
3842begin
3843  Result := JS_GetArrayBufferViewBuffer(@self, obj, isSharedMemory);
3844end;
3845
3846function JSContext.GetArrayBufferViewBuffer(var obj: PJSObject): PJSObject;
3847var
3848  isSharedMemory: Boolean;
3849begin
3850  Result := JS_GetArrayBufferViewBuffer(@self, obj, isSharedMemory);
3851end;
3852
3853function JSContext.GetIsRunning: boolean;
3854begin
3855  result := JS_IsRunning(@self);
3856end;
3857
3858procedure JSContext.FreeCompileOptions(opt: PJSCompileOptions);
3859begin
3860  JS_FreeCompileOptions(opt);
3861end;
3862
3863procedure JSContext.FreeRootedObject(obj: PJSRootedObject);
3864var
3865  curr: PJSRootedObject;
3866begin
3867  curr := obj.stack.Last;
3868  while curr.ptr = nil do curr := curr.prev;
3869  if curr <> obj then
3870    raise ESMException.Create('FreeRootedObject Stack error');
3871  JS_FreeRootedObject(obj);
3872end;
3873
3874procedure JSContext.FreeRootedString(str: PJSRootedString);
3875begin
3876  if ppointer(str.stack)^ <> str then
3877    raise ESMException.Create('FreeRootedString Stack error');
3878  JS_FreeRootedString(str);
3879end;
3880
3881procedure JSContext.FreeRootedValue(str: PJSRootedValue);
3882begin
3883  if ppointer(str.stack)^ <> str then
3884    raise ESMException.Create('FreeRootedValue Stack error');
3885  JS_FreeRootedValue(str);
3886end;
3887
3888function JSContext.NewRootedObject(obj: PJSObject): PJSRootedObject;
3889begin
3890  Result := JS_NewRootedObject(@Self, obj);
3891end;
3892
3893function JSContext.NewRootedString(obj: PJSString): PJSRootedString;
3894begin
3895  Result := JS_NewRootedString(@Self, obj)
3896end;
3897
3898function JSContext.NewRootedValue(val: jsval): PJSRootedValue;
3899begin
3900  Result := JS_NewRootedValue(@Self, val._l.asBits)
3901end;
3902
3903function JSContext.NewSharedArrayBuffer(nbytes: uint32): PJSObject;
3904begin
3905  Result := JS_NewSharedArrayBuffer(@Self, nbytes);
3906end;
3907
3908function JSContext.NewUint16Array(nelements: uint32): PJSObject;
3909begin
3910  Result := JS_NewUint16Array(@Self, nelements);
3911end;
3912
3913function JSContext.NewUint16ArrayFromArray(var arr: PJSObject): PJSObject;
3914begin
3915  Result := JS_NewUInt16ArrayFromArray(@Self, arr);
3916end;
3917
3918function JSContext.NewUint16ArrayWithBuffer(var arrayBuffer: PJSObject;
3919  byteOffset: uint32; length: int32): PJSObject;
3920begin
3921  Result := JS_NewUInt16ArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
3922end;
3923
3924function JSContext.NewUint32Array(nelements: uint32): PJSObject;
3925begin
3926  Result := JS_NewUInt32Array(@Self, nelements);
3927end;
3928
3929function JSContext.NewUint32ArrayFromArray(var arr: PJSObject): PJSObject;
3930begin
3931  Result := JS_NewUInt32ArrayFromArray(@Self, arr);
3932end;
3933
3934function JSContext.NewUint32ArrayWithBuffer(var arrayBuffer: PJSObject;
3935  byteOffset: uint32; length: int32): PJSObject;
3936begin
3937  Result := JS_NewUInt32ArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
3938end;
3939
3940function JSContext.NewUint8Array(nelements: uint32): PJSObject;
3941begin
3942  Result := JS_NewuInt8Array(@Self, nelements);
3943end;
3944
3945function JSContext.NewUint8ArrayFromArray(var arr: PJSObject): PJSObject;
3946begin
3947  Result := JS_NewUInt8ArrayFromArray(@Self, arr);
3948end;
3949
3950function JSContext.NewUint8ArrayWithBuffer(var arrayBuffer: PJSObject;
3951  byteOffset: uint32; length: int32): PJSObject;
3952begin
3953  Result := JS_NewUInt8ArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
3954end;
3955
3956function JSContext.NewUint8ClampedArray(nelements: uint32): PJSObject;
3957begin
3958  Result := JS_NewUint8ClampedArray(@Self, nelements);
3959end;
3960
3961function JSContext.NewUint8ClampedArrayFromArray(var arr: PJSObject): PJSObject;
3962begin
3963  Result := JS_NewUint8ClampedArrayFromArray(@Self, arr);
3964end;
3965
3966function JSContext.NewUint8ClampedArrayWithBuffer(var arrayBuffer: PJSObject;
3967  byteOffset: uint32; length: int32): PJSObject;
3968begin
3969  Result := JS_NewUint8ClampedArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
3970end;
3971
3972procedure strFinalizeOp(fin: PJSStringFinalizer; chars: PCChar16);  cdecl;
3973begin
3974
3975end;
3976
3977function JSContext.NewExternalString(const Value: SynUnicode): PJSString;
3978begin
3979  Result := JS_NewExternalString(@Self,  pointer(Value), length(Value), @strFinalizer);
3980end;
3981
3982//function JSContext.AtomizeAndPinString(const Value: SynUnicode): PJSString; {$ifdef HASINLINE}inline;{$endif}
3983//begin
3984//  Result := JS_AtomizeAndPinStringN(@Self,  pointer(Value), length(Value));
3985//end;
3986
3987function JSContext.NewFloat32Array(nelements: uint32): PJSObject;
3988begin
3989  Result := JS_NewFloat32Array(@Self, nelements);
3990end;
3991
3992function JSContext.NewFloat32ArrayFromArray(var arr: PJSObject): PJSObject;
3993begin
3994  Result := JS_NewFloat32ArrayFromArray(@Self, arr);
3995end;
3996
3997function JSContext.NewFloat32ArrayWithBuffer(var arrayBuffer: PJSObject;
3998  byteOffset: uint32; length: int32): PJSObject;
3999begin
4000  Result := JS_NewFloat32ArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
4001end;
4002
4003function JSContext.NewFloat64Array(nelements: uint32): PJSObject;
4004begin
4005  Result := JS_NewFloat64Array(@Self, nelements);
4006end;
4007
4008function JSContext.NewFloat64ArrayFromArray(var arr: PJSObject): PJSObject;
4009begin
4010  Result := JS_NewFloat64ArrayFromArray(@Self, arr);
4011end;
4012
4013function JSContext.NewFloat64ArrayWithBuffer(var arrayBuffer: PJSObject;
4014  byteOffset: uint32; length: int32): PJSObject;
4015begin
4016  Result := JS_NewFloat64ArrayWithBuffer(@Self, arrayBuffer, byteOffset, length);
4017end;
4018
4019function JSContext.NewFunction(call: JSNative; nargs: uintN; flags: uintN;
4020  name: PCChar): PJSObject;
4021begin
4022  Result := JS_NewFunction(@Self, call, nargs, flags, name);
4023end;
4024
4025function JSContext.DefineDebuggerObject(var obj: PJSObject): boolean;
4026begin
4027  Result := JS_DefineDebuggerObject(@Self, obj);
4028end;
4029
4030function JSContext.NewCompileOptions: PJSCompileOptions;
4031begin
4032  result := JS_NewCompileOptions(@self);
4033end;
4034
4035function JSContext.CompileModule(var obj: PJSObject; opts: PJSCompileOptions;
4036  chars: PCChar16; length: size_t): PJSObject;
4037begin
4038  Result := JS_CompileModule(@Self, obj, opts, chars, length);
4039end;
4040
4041function JSContext.CompileScript(bytes: PCChar;
4042  length: size_t; opts: PJSCompileOptions; out script: PJSScript): boolean;
4043begin
4044  Result := JS_CompileScript(@Self, bytes, length, opts, script);
4045end;
4046
4047function JSContext.CompileUCScript(chars: PCChar16; length: size_t;
4048  opts: PJSCompileOptions; out script: PJSScript): boolean;
4049begin
4050  Result := JS_CompileUCScript(@Self, chars, length, opts, script);
4051end;
4052
4053function JSContext.EvaluateScript(opts: PJSCompileOptions; bytes: PCChar; length: size_t;
4054  out rval: jsval): Boolean;
4055begin
4056  Result := JS_EvaluateScript(@Self, opts, bytes, length, rval);
4057end;
4058
4059function JSContext.EvaluateUCScript(opts: PJSCompileOptions; chars: PCChar16; length: size_t;
4060  out rval: jsval): Boolean;
4061begin
4062  Result := JS_EvaluateUCScript(@Self, opts, chars, length, rval);
4063end;
4064
4065function JSContext.ExecuteScript(var script: PJSScript; out rval: jsval): Boolean;
4066begin
4067  Result := JS_ExecuteScript(@Self, script, rval);
4068end;
4069
4070function JSContext.New(var ctor: PJSObject; argc: uintN; argv: PjsvalVector): PJSObject;
4071var
4072    args: JSHandleValueArray;
4073begin
4074  args.length := argc;
4075  args.elements_ := argv;
4076  Result := JS_New(@self, ctor, args);
4077end;
4078
4079function JSContext.NewArrayBuffer(nbytes: uint32): PJSObject;
4080begin
4081  Result := JS_NewArrayBuffer(@Self, nbytes);
4082end;
4083
4084function JSContext.NewArrayObject(length: size_t;
4085  vector: PjsvalVector): PJSObject;
4086var
4087    contents: JSHandleValueArray;
4088begin
4089  contents.length := length;
4090  contents.elements_ := vector;
4091  Result := JS_NewArrayObject2(@Self, contents);
4092end;
4093
4094function JSContext.NewArrayObject(length: size_t): PJSObject;
4095begin
4096  Result := JS_NewArrayObject(@Self, length);
4097end;
4098
4099function JSContext.InitCTypesClass(var obj: PJSObject): boolean;
4100begin
4101  Result := JS_InitCTypesClass(@Self, obj);
4102end;
4103
4104function JSContext.InitReflectParse(var obj: PJSObject): boolean;
4105begin
4106  Result := JS_InitReflectParse(@Self, obj);
4107end;
4108
4109function JSContext.InitModuleClasses(var obj: PJSObject): boolean;
4110begin
4111  Result := JS_InitModuleClasses(@Self, obj);
4112end;
4113
4114function JSContext.NewJSString(const Value: RawUTF8): PJSString;
4115begin
4116  if Value = '' then
4117    result := JS_GetEmptyString(@self) else
4118    result := JS_NewStringCopyUTF8Z(@self, pointer(Value));
4119end;
4120
4121function JSContextOptions.getOptions(const Index: Integer): Boolean;
4122begin
4123   Result := (pword(@self)^ and (1 shl Index)) <> 0;
4124end;
4125
4126procedure JSContextOptions.setOptions(const Index: Integer;
4127  const Value: Boolean);
4128var
4129  val: uint16;
4130begin
4131  val := 1 shl Index;
4132  if Value then
4133    pword(@self)^ := pword(@self)^ or val
4134  else
4135    pword(@self)^ := pword(@self)^ and (not val);
4136end;
4137
4138procedure JSContext.GC;
4139begin
4140  JS_GC(@self);
4141end;
4142
4143function JSContext.GetEmptyString: PJSString;
4144begin
4145  Result := JS_GetEmptyString(@self);
4146end;
4147
4148function JSContext.GetWarningReporter: JSWarningReporter;
4149begin
4150  Result := JS_GetWarningReporter(@self);
4151end;
4152
4153function JSContext.GetGCParameter(key: JSGCParamKey): uint32;
4154begin
4155  Result := JS_GetGCParameter(@Self, key);
4156end;
4157
4158function JSContext.GetNowMs: int64;
4159begin
4160  Result := JS_Now;
4161end;
4162
4163class function JSContext.CreateNew(maxbytes: uint32; maxNurseryBytes: uint32; parentContext: PJSContext): PJSContext;
4164begin
4165  with TSynFPUException.ForLibraryCode do begin
4166    Result := JS_NewContext(maxbytes, maxNurseryBytes, parentContext);
4167    InitSelfHostedCode(Result);
4168  end;
4169end;
4170
4171function JSContext.GetOptions: PJSContextOptions;
4172begin
4173  Result := JS_GetContextOptions(@self);
4174end;
4175
4176procedure JSContext.RequestInterruptCallback;
4177begin
4178  JS_RequestInterruptCallback(@self);
4179end;
4180
4181procedure JSContext.SetWarningReporter(reporter: JSWarningReporter);
4182begin
4183  JS_SetWarningReporter(@self, reporter);
4184end;
4185
4186procedure JSContext.SetGCParameter(key: JSGCParamKey; const Value: uint32);
4187begin
4188  JS_SetGCParameter(@Self, key, Value);
4189end;
4190
4191procedure JSContext.SetGCParametersBasedOnAvailableMemory(availMem: uint32);
4192begin
4193  JS_SetGCParametersBasedOnAvailableMemory(@Self, availMem);
4194end;
4195
4196procedure JSContext.SetNativeStackQuota(systemCodeStackSize: size_t);
4197begin
4198  JS_SetNativeStackQuota(@Self, systemCodeStackSize);
4199end;
4200
4201{ JSObject }
4202
4203function JSObject.isArray(cx: PJSContext): Boolean;
4204var
4205  _isArray: Boolean;
4206  obj: PJSObject;
4207begin
4208  obj := @Self;
4209  Result := JS_IsArrayObject(cx, obj, _isArray) and _isArray;
4210end;
4211
4212function JSObject.IsArrayBufferObject: Boolean;
4213begin
4214  result := JS_IsArrayBufferObject(@self)
4215end;
4216
4217function JSObject.IsArrayBufferViewObject: Boolean;
4218begin
4219  result := JS_IsArrayBufferViewObject(@self)
4220end;
4221
4222function JSObject.isDate(cx: PJSContext): Boolean;
4223var
4224  _isDate: Boolean;
4225  obj: PJSObject;
4226begin
4227  obj := @Self;
4228  Result := JS_ObjectIsDate(cx, obj, _isDate) and _isDate;
4229end;
4230
4231function JSObject.IsFloat32Array: Boolean;
4232begin
4233  result := JS_IsFloat32Array(@self);
4234end;
4235
4236function JSObject.IsFloat64Array: Boolean;
4237begin
4238  result := JS_IsFloat64Array(@self);
4239end;
4240
4241function JSObject.isFunction(cx: PJSContext): Boolean;
4242begin
4243  Result := JS_ObjectIsFunction(cx, @Self);
4244end;
4245
4246function JSObject.IsInt16Array: Boolean;
4247begin
4248  result := JS_IsInt16Array(@self)
4249end;
4250
4251function JSObject.IsInt32Array: Boolean;
4252begin
4253  result := JS_IsInt32Array(@self)
4254end;
4255
4256function JSObject.IsInt8Array: Boolean;
4257begin
4258  result := JS_IsInt8Array(@self)
4259end;
4260
4261function JSObject.IsMappedArrayBufferObject(obj: PJSObject): Boolean;
4262begin
4263  result := JS_IsMappedArrayBufferObject(@self);
4264end;
4265
4266function JSObject.IsSharedArrayBufferObject: Boolean;
4267begin
4268  result := JS_IsSharedArrayBufferObject(@self)
4269end;
4270
4271function JSObject.IsTypedArrayObject: Boolean;
4272begin
4273  result := JS_IsTypedArrayObject(@self)
4274end;
4275
4276function JSObject.IsUint16Array: Boolean;
4277begin
4278  result := JS_IsUInt16Array(@self)
4279end;
4280
4281function JSObject.IsUint32Array: Boolean;
4282begin
4283  result := JS_IsUInt32Array(@self);
4284end;
4285
4286function JSObject.IsUint8Array: Boolean;
4287begin
4288  result := JS_IsUint8Array(@self)
4289end;
4290
4291function JSObject.IsUint8ClampedArray: Boolean;
4292begin
4293  result := JS_IsUint8ClampedArray(@self)
4294end;
4295
4296function JSObject.GetArrayBufferViewData(out isSharedMemory: Boolean;
4297  nogc: PJSAutoCheckCannotGC): Pointer;
4298begin
4299  result := JS_GetArrayBufferViewData(@self, isSharedMemory, nogc);
4300end;
4301
4302function JSObject.RunMethod(cx: PJSContext; const name: PCChar;
4303  out rval: jsval): Boolean;
4304begin
4305  Result := CallFunctionName(cx, name, 0, nil, rval);
4306end;
4307
4308function JSObject.RunMethod(cx: PJSContext; const name: PCChar; arg: jsval;
4309  out rval: jsval): Boolean;
4310begin
4311  Result := CallFunctionName(cx, name, 1, @arg, rval);
4312end;
4313
4314function JSObject.RunMethod(cx: PJSContext; const name: PCChar;
4315  args: TjsvalDynArray; out rval: jsval): Boolean;
4316begin
4317  Result := CallFunctionName(cx, name, Length(args), @args[0], rval);
4318end;
4319
4320function JSObject.GetInstancePrivate(cx: PJSContext; clasp: PJSClass): Pointer;
4321var
4322  obj: PJSObject;
4323begin
4324  obj := @Self;
4325  result := JS_GetInstancePrivate(cx, obj, clasp, nil);
4326end;
4327
4328function JSObject.GetInt16ArrayData(out isSharedMemory: Boolean;
4329  nogc: PJSAutoCheckCannotGC): Pint16Vector;
4330begin
4331  result := JS_GetInt16ArrayData(@self, isSharedMemory, nogc);
4332end;
4333
4334function JSObject.GetInt32ArrayData(out isSharedMemory: Boolean;
4335  nogc: PJSAutoCheckCannotGC): Pint32Vector;
4336begin
4337  result := JS_GetInt32ArrayData(@self, isSharedMemory, nogc);
4338end;
4339
4340function JSObject.GetInt8ArrayData(out isSharedMemory: Boolean;
4341  nogc: PJSAutoCheckCannotGC): Pint8Vector;
4342begin
4343  result := JS_GetInt8ArrayData(@self, isSharedMemory, nogc);
4344end;
4345
4346function JSObject.GetObjectAsArrayBuffer(out length: uint32;
4347  out Data: Puint8Vector): PJSObject;
4348begin
4349  result := JS_GetObjectAsArrayBuffer(@self, length, data);
4350end;
4351
4352function JSObject.GetObjectAsArrayBufferView(out length: uint32;
4353  out isSharedMemory: Boolean; out Data: Puint8Vector): PJSObject;
4354begin
4355  result := JS_GetObjectAsArrayBufferView(@self, length, isSharedMemory, data);
4356end;
4357
4358function JSObject.GetObjectAsFloat32Array(out length: uint32;
4359  out isSharedMemory: Boolean; out Data: Pfloat32Vector): PJSObject;
4360begin
4361  result := JS_GetObjectAsFloat32Array(@self, length, isSharedMemory, data);
4362end;
4363
4364function JSObject.GetObjectAsFloat64Array(out length: uint32;
4365  out isSharedMemory: Boolean; out Data: Pfloat64Vector): PJSObject;
4366begin
4367  result := JS_GetObjectAsFloat64Array(@self, length, isSharedMemory, data);
4368end;
4369
4370function JSObject.GetObjectAsInt16Array(out length: uint32;
4371  out isSharedMemory: Boolean; out Data: Pint16Vector): PJSObject;
4372begin
4373  result := JS_GetObjectAsInt16Array(@self, length, isSharedMemory, data);
4374end;
4375
4376function JSObject.GetObjectAsInt32Array(out length: uint32;
4377  out isSharedMemory: Boolean; out Data: Pint32Vector): PJSObject;
4378begin
4379  result := JS_GetObjectAsInt32Array(@self, length, isSharedMemory, data);
4380end;
4381
4382function JSObject.GetObjectAsInt8Array(out length: uint32;
4383  out isSharedMemory: Boolean; out Data: Pint8Vector): PJSObject;
4384begin
4385  result := JS_GetObjectAsInt8Array(@self, length, isSharedMemory, data)
4386end;
4387
4388function JSObject.GetObjectAsUint16Array(out length: uint32;
4389  out isSharedMemory: Boolean; out Data: Puint16Vector): PJSObject;
4390begin
4391  result := JS_GetObjectAsUInt16Array(@self, length, isSharedMemory, data);
4392end;
4393
4394function JSObject.GetObjectAsUint32Array(out length: uint32;
4395  out isSharedMemory: Boolean; out Data: Puint32Vector): PJSObject;
4396begin
4397  result := JS_GetObjectAsUint32Array(@self, length, isSharedMemory, data);
4398end;
4399
4400function JSObject.GetObjectAsUint8Array(out length: uint32;
4401  out isSharedMemory: Boolean; out Data: Puint8Vector): PJSObject;
4402begin
4403  result := JS_GetObjectAsUInt8Array(@self, length, isSharedMemory, data)
4404end;
4405
4406function JSObject.GetObjectAsUint8ClampedArray(out length: uint32;
4407  out isSharedMemory: Boolean; out Data: Puint8Vector): PJSObject;
4408begin
4409  result := JS_GetObjectAsUint8ClampedArray(@self, length, isSharedMemory, data)
4410end;
4411
4412function JSObject.GetPrivate: Pointer;
4413begin
4414  Result := JS_GetPrivate(@self);
4415end;
4416
4417function JSObject.GetProperty(cx: PJSContext; const name: PCChar;
4418  out vp: jsval): boolean;
4419var
4420  obj: PJSObject;
4421begin
4422  obj := @Self;
4423  Result := JS_GetProperty(cx, obj, name, vp);
4424end;
4425
4426function JSObject.GetPropertyById(cx: PJSContext; const id: jsid;
4427  out vp: jsval): boolean;
4428var
4429  obj: PJSObject;
4430  _id: jsid;
4431begin
4432  obj := @Self;
4433  _id := id;
4434  Result := JS_GetPropertyById(cx, obj, _id, vp);
4435end;
4436
4437function JSObject.GetPropValue(cx: PJSContext; const name: SynUnicode): jsval;
4438begin
4439  {$ifdef WITHASSERT}
4440  Assert(
4441  {$ENDIF}
4442  GetUCProperty(cx, Pointer(name), Length(name), Result)
4443  {$ifdef WITHASSERT}
4444  );
4445  {$ENDIF}
4446end;
4447
4448function JSObject.GetPrototype(cx: PJSContext; out protop: PJSObject): Boolean;
4449var
4450  obj: PJSObject;
4451begin
4452  obj := @Self;
4453  Result := JS_GetPrototype(cx, obj, protop);
4454end;
4455
4456function JSObject.GetReservedSlot(index: uint32): jsval;
4457begin
4458  result._l.asBits := JS_GetReservedSlot(@Self, index)
4459end;
4460
4461function JSObject.GetSharedArrayBufferByteLength: uint32;
4462begin
4463  result := JS_GetSharedArrayBufferByteLength(@self);
4464end;
4465
4466function JSObject.GetTypedArrayByteLength: uint32;
4467begin
4468  result := JS_GetTypedArrayLength(@self);
4469end;
4470
4471function JSObject.GetTypedArrayByteOffset: uint32;
4472begin
4473  result := JS_GetTypedArrayByteOffset(@self);
4474end;
4475
4476function JSObject.GetTypedArrayLength: uint32;
4477begin
4478  result := JS_GetTypedArrayLength(@self);
4479end;
4480
4481function JSObject.GetTypedArraySharedness: Boolean;
4482begin
4483  result := JS_GetTypedArraySharedness(@self)
4484end;
4485
4486function JSObject.AlreadyHasOwnUCProperty(cx: PJSContext; const name: PCChar16;
4487  namelen: size_t): Boolean;
4488var
4489  obj: PJSObject;
4490  foundp: Boolean;
4491begin
4492  obj := @Self;
4493  Result := JS_AlreadyHasOwnUCProperty(cx, obj, name, namelen, foundp) and foundp;
4494end;
4495
4496function JSObject.ArrayBufferHasData: Boolean;
4497begin
4498  result := JS_ArrayBufferHasData(@self);
4499end;
4500
4501function JSObject.CallFunction(cx: PJSContext; var fun: PJSFunction;
4502  argc: uintN; argv: PjsvalVector; out rval: jsval): Boolean;
4503var obj: PJSObject;
4504    args: JSHandleValueArray;
4505begin
4506  obj := @Self;
4507  args.length := argc;
4508  args.elements_ := argv;
4509  Result := JS_CallFunction(cx, obj, fun, args, rval);
4510end;
4511
4512function JSObject.CallFunctionName(cx: PJSContext; const name: PCChar;
4513  argc: uintN; argv: PjsvalVector; out rval: jsval): Boolean;
4514var obj: PJSObject;
4515    args: JSHandleValueArray;
4516begin
4517  obj := @Self;
4518  args.length := argc;
4519  args.elements_ := argv;
4520  Result := JS_CallFunctionName(cx, obj, name, args, rval);
4521end;
4522
4523function JSObject.CallFunctionValue(cx: PJSContext; val: jsval; argc: uintN;
4524  argv: PjsvalVector; out rval: jsval): Boolean;
4525var obj: PJSObject;
4526    args: JSHandleValueArray;
4527begin
4528  obj := @Self;
4529  args.length := argc;
4530  args.elements_ := argv;
4531  Result := JS_CallFunctionValue(cx, obj, val, args, rval);
4532end;
4533
4534const
4535  /// API extension: OR this into indent to avoid pretty-printing the decompiled
4536  // source resulting from JS_DecompileFunction{,Body}.
4537  JS_DONT_PRETTY_PRINT = $8000;
4538  prettyPrintAr: array[boolean] of uintN = (JS_DONT_PRETTY_PRINT, 0);
4539function JSObject.DecompileFunction(cx: PJSContext;
4540  PrettyPrint: Boolean): PJSString;
4541var
4542  fun: PJSFunction;
4543begin
4544  fun := @self;
4545  Result := JS_DecompileFunction(cx, fun, prettyPrintAr[PrettyPrint]);
4546end;
4547
4548function JSObject.DefineFunction(cx: PJSContext; name: PCChar; call: JSNative;
4549  nargs, attrs: uintN): PJSFunction;
4550var obj: PJSObject;
4551begin
4552  obj := @Self;
4553  Result := JS_DefineFunction(cx, obj, name, call, nargs, attrs);
4554end;
4555
4556function JSObject.DefineFunctions(cx: PJSContext; fs: PJSFunctionSpec;
4557  behavior: JSPropertyDefinitionBehavior): Boolean;
4558var obj: PJSObject;
4559begin
4560  obj := @Self;
4561  Result := JS_DefineFunctions(cx, obj, fs, behavior);
4562end;
4563
4564function JSObject.DefineProperties(cx: PJSContext;
4565  ps: PJSPropertySpec): boolean;
4566var obj: PJSObject;
4567begin
4568  obj := @Self;
4569  result := JS_DefineProperties(cx, obj, ps)
4570end;
4571
4572function JSObject.DefineProperty(cx: PJSContext; const name: PCChar;
4573  const value: jsval; attrs: uint32; getter, setter: JSNative): boolean;
4574var obj: PJSObject;
4575begin
4576  obj := @Self;
4577  result := JS_DefineProperty(cx, obj, name, pjsval(@value)^, attrs, getter, setter)
4578end;
4579
4580function JSObject.DefinePropertyById(cx: PJSContext; var id: jsid;
4581  const value: jsval; attrs: uint32; getter, setter: JSNative): boolean;
4582var obj: PJSObject;
4583begin
4584  obj := @Self;
4585  result := JS_DefinePropertyById(cx, obj, id, pjsval(@value)^, attrs, getter, setter)
4586end;
4587
4588function JSObject.DefineUCFunction(cx: PJSContext; name: PCChar16;
4589  namelen: size_t; call: JSNative; nargs, attrs: uintN): PJSFunction;
4590var obj: PJSObject;
4591begin
4592  obj := @Self;
4593  Result := JS_DefineUCFunction(cx, obj, name, namelen, call, nargs, attrs);
4594end;
4595
4596function JSObject.DefineUCProperty(cx: PJSContext; const name: SynUnicode;
4597  const value: jsval; attrs: uint32; getter, setter: JSNative): Boolean;
4598var obj: PJSObject;
4599begin
4600  obj := @Self;
4601  result := JS_DefineUCProperty(cx, obj, Pointer(name), Length(name), pjsval(@value)^, attrs, getter, setter)
4602end;
4603
4604function JSObject.DefineUCProperty(cx: PJSContext; const name: PCChar16;
4605  namelen: size_t; const value: jsval; attrs: uint32; getter,
4606  setter: JSNative): Boolean;
4607var obj: PJSObject;
4608begin
4609  obj := @Self;
4610  result := JS_DefineUCProperty(cx, obj, name, namelen, pjsval(@value)^, attrs, getter, setter)
4611end;
4612
4613function JSObject.DeleteElement(cx: PJSContext; index: uint32;
4614  out res: JS_ObjectOpResult): Boolean;
4615var obj: PJSObject;
4616begin
4617  obj := @Self;
4618  result := JS_DeleteElement(cx, obj, index, res);
4619end;
4620
4621function JSObject.DeletePropertyById(cx: PJSContext; const id: jsid;
4622  out res: JS_ObjectOpResult): Boolean;
4623var obj: PJSObject;
4624    _id: jsid;
4625begin
4626  obj := @Self;
4627  _id := id;
4628  Result := JS_DeletePropertyById(cx, obj, _id, res);
4629end;
4630
4631function JSObject.Enumerate(cx: PJSContext; out length: size_t; out data: PjsidVector): PJSIdArray;
4632var obj: PJSObject;
4633begin
4634  obj := @Self;
4635  Result := JS_EnumerateToAutoIdVector(cx, obj, length, data);
4636  {$ifdef WITHASSERT}
4637  Assert(Assigned(Result));
4638  {$ENDIF}
4639end;
4640
4641function JSObject.GetUCProperty(cx: PJSContext; const name: PCChar16;
4642  namelen: size_t; out vp: jsval): boolean;
4643var obj: PJSObject;
4644begin
4645  obj := @Self;
4646  Result := JS_GetUCProperty(cx, obj, name, namelen, vp);
4647end;
4648
4649function JSObject.GetUint16ArrayData(out isSharedMemory: Boolean;
4650  nogc: PJSAutoCheckCannotGC): Puint16Vector;
4651begin
4652  result := JS_GetUInt16ArrayData(@self, isSharedMemory, nogc);
4653end;
4654
4655function JSObject.GetUint32ArrayData(out isSharedMemory: Boolean;
4656  nogc: PJSAutoCheckCannotGC): Puint32Vector;
4657begin
4658  result := JS_GetUint32ArrayData(@self, isSharedMemory, nogc);
4659end;
4660
4661function JSObject.GetUint8ArrayData(out isSharedMemory: Boolean;
4662  nogc: PJSAutoCheckCannotGC): Puint8Vector;
4663begin
4664  result := JS_GetUInt8ArrayData(@self, isSharedMemory, nogc);
4665end;
4666
4667function JSObject.GetUint8ArrayData: Puint8Vector;
4668var isShared: Boolean;
4669begin
4670  result := JS_GetUInt8ArrayData(@self, isShared, nil);
4671end;
4672
4673function JSObject.GetUint8ClampedArrayData(out isSharedMemory: Boolean;
4674  nogc: PJSAutoCheckCannotGC): Puint8Vector;
4675begin
4676  result := JS_GetUint8ClampedArrayData(@self, isSharedMemory, nogc);
4677end;
4678
4679function JSObject.HasInstance(cx: PJSContext; var val: jsval): Boolean;
4680var obj: PJSObject;
4681    res: Boolean;
4682begin
4683  obj := @Self;
4684  Result := JS_HasInstance(cx, obj, val, res) and res;
4685end;
4686
4687function JSObject.HasProperty(cx: PJSContext; const name: PCChar): Boolean;
4688var obj: PJSObject;
4689    found: Boolean;
4690begin
4691  obj := @Self;
4692  Result := JS_HasProperty(cx, obj, name, found) and found;
4693end;
4694
4695function JSObject.HasUCProperty(cx: PJSContext; const name: PCChar16;
4696  namelen: size_t; out found: Boolean): Boolean;
4697var obj: PJSObject;
4698begin
4699  obj := @Self;
4700  Result := JS_HasUCProperty(cx, obj, name, namelen, found);
4701end;
4702
4703function JSObject.InitClass(cx: PJSContext; var parent_proto: PJSObject;
4704  clasp: PJSClass; _constructor: JSNative; nargs: Cardinal; ps: PJSPropertySpec;
4705  fs: PJSFunctionSpec; static_ps: PJSPropertySpec;
4706  static_fs: PJSFunctionSpec): PJSObject;
4707var obj: PJSObject;
4708begin
4709  obj := @Self;
4710  Result := JS_InitClass(cx, obj, parent_proto, clasp, _constructor, nargs, ps, fs, static_ps, static_fs);
4711end;
4712
4713function JSObject.GetArrayBufferByteLength: uint32;
4714begin
4715  result := JS_GetArrayBufferByteLength(@self);
4716end;
4717
4718function JSObject.GetArrayBufferData: Puint8Vector;
4719var isShared: Boolean;
4720begin
4721  result := JS_GetArrayBufferData(@self, isShared, nil);
4722end;
4723
4724function JSObject.GetArrayBufferData(out isSharedMemory: Boolean;
4725  nogc: PJSAutoCheckCannotGC): Puint8Vector;
4726begin
4727  result := JS_GetArrayBufferData(@self, isSharedMemory, nogc);
4728end;
4729
4730function JSObject.GetArrayBufferViewByteLength: uint32;
4731begin
4732  result := JS_GetArrayBufferViewByteLength(@self);
4733end;
4734
4735function JSObject.GetArrayBufferViewType: JSArrayBufferViewType;
4736begin
4737  result := JS_GetArrayBufferViewType(@self);
4738end;
4739
4740function JSObject.GetArrayLength(cx: PJSContext; out length: uint32): Boolean;
4741var obj: PJSObject;
4742begin
4743  obj := @Self;
4744  result := JS_GetArrayLength(cx, obj, length);
4745end;
4746
4747function JSObject.GetClass: PJSClass;
4748begin
4749  result := JS_GetClass(@self);
4750end;
4751
4752function JSObject.GetConstructor(cx: PJSContext): PJSObject;
4753var obj: PJSObject;
4754begin
4755  obj := @Self;
4756  Result := JS_GetConstructor(cx, obj);
4757end;
4758
4759function JSObject.GetElement(cx: PJSContext; index: uint32;
4760  out vp: jsval): Boolean;
4761var obj: PJSObject;
4762begin
4763  obj := @Self;
4764  result := JS_GetElement(cx, obj, index, vp);
4765end;
4766
4767function JSObject.GetFloat32ArrayData(out isSharedMemory: Boolean;
4768  nogc: PJSAutoCheckCannotGC): Pfloat32Vector;
4769begin
4770  result := JS_GetFloat32ArrayData(@self, isSharedMemory, nogc);
4771end;
4772
4773function JSObject.GetFloat64ArrayData(out isSharedMemory: Boolean;
4774  nogc: PJSAutoCheckCannotGC): Pfloat64Vector;
4775begin
4776  result := JS_GetFloat64ArrayData(@self, isSharedMemory, nogc);
4777end;
4778
4779function JSObject.GetFunctionId: PJSString;
4780begin
4781  Result := JS_GetFunctionId(@self);
4782end;
4783
4784function JSObject.SetElement(cx: PJSContext; index: uint32;
4785  const vp: jsval): Boolean;
4786var obj: PJSObject;
4787begin
4788  obj := @Self;
4789  result := JS_SetElement(cx, obj, index, pjsval(@vp)^);
4790end;
4791
4792procedure JSObject.SetPrivate(data: Pointer);
4793begin
4794  JS_SetPrivate(@self, data);
4795end;
4796
4797function JSObject.SetProperty(cx: PJSContext; const name: PCChar;
4798  const vp: jsval): Boolean;
4799var obj: PJSObject;
4800begin
4801  obj := @Self;
4802  Result := JS_SetProperty(cx, obj, name, pjsval(@vp)^);
4803end;
4804
4805function JSObject.SetPrototype(cx: PJSContext; var proto: PJSObject): Boolean;
4806var
4807  obj: PJSObject;
4808begin
4809  obj := @Self;
4810  Result := JS_SetPrototype(cx, obj, proto);
4811end;
4812
4813procedure JSObject.SetReservedSlot(index: uint32; v: jsval);
4814begin
4815  JS_SetReservedSlot(@Self, index, v);
4816end;
4817
4818function JSObject.SetUCProperty(cx: PJSContext; const name: PCChar16;
4819  namelen: size_t; const vp: jsval): boolean;
4820var obj: PJSObject;
4821begin
4822  obj := @Self;
4823  Result := JS_SetUCProperty(cx, obj, name, namelen, pjsval(@vp)^);
4824end;
4825
4826function JSObject.ToJSValue: jsval;
4827begin
4828  Result.asObject := @self;
4829end;
4830
4831function JSObject.GetBufferDataAndLength(out data: Puint8Vector; out len: uint32): boolean;
4832var
4833  isShared: boolean;
4834begin
4835  if Self.IsArrayBufferViewObject then begin
4836    Result := Self.GetObjectAsArrayBufferView(len, isShared, data) <> nil;
4837  end else if Self.IsArrayBufferObject then begin
4838    data := Self.GetArrayBufferData;
4839    len := Self.GetArrayBufferByteLength;
4840    Result := True
4841  end else
4842    Result := False;
4843end;
4844
4845{ ESMException }
4846
4847constructor ESMException.CreateWithTrace(const AFileName: RawUTF8; AJSErrorNum, ALineNum: integer; AMessage: string; const AStackTrace: SynUnicode);
4848{$ifndef SM_DEBUG}
4849const
4850  MODULE_START: SynUnicode = #10'Module.';
4851var
4852  appStackEnd: SizeInt;
4853{$endif}
4854begin
4855  Create(AMessage);
4856  FJSErrorNum := AJSErrorNum;
4857  if AFileName='' then
4858    FFileName := '<>'
4859  else
4860    FFileName := AFileName;
4861  FLineNum := ALineNum;
4862  {$ifdef SM_DEBUG}
4863  FJSStackTrace := AStackTrace;
4864  {$else}
4865  if length(AStackTrace) = 0 then
4866    FJSStackTrace := ''
4867  else begin
4868    appStackEnd := Pos(MODULE_START, AStackTrace);
4869    if appStackEnd = 0 then
4870      FJSStackTrace := AStackTrace
4871    else
4872      FJSStackTrace := Copy(AStackTrace, 0, appStackEnd - 1); // last \n
4873  end;
4874  {$endif}
4875end;
4876
4877procedure ESMException.WriteFormatted(WR: TTextWriter);
4878begin
4879  WR.AddJSONEscape(pointer(FileName), Length(fileName));
4880    WR.Add(':'); WR.Add(Line);
4881  WR.AddShort('\n\nError: ');
4882  WR.AddJSONEscapeString(Message); WR.AddShort('\n');
4883  {$ifdef SM_DEBUG}
4884    WR.AddJSONEscapeString(Stack);
4885  {$else}
4886   WR.AddJSONEscapeW(pointer(Stack), length(Stack));
4887  {$endif}
4888end;
4889
4890{$ifndef NOEXCEPTIONINTERCEPT}
4891function ESMException.CustomLog(
4892  WR: TTextWriter; const Context: TSynLogExceptionContext): boolean;
4893begin
4894  (Context.EInstance as ESMException).WriteFormatted(WR);
4895  result := true; // do not append a address
4896end;
4897{$endif}
4898
4899{ JSArgRec }
4900
4901function JSArgRec.getArgv: PjsvalVector;
4902begin
4903  Result := @rec.argv;
4904end;
4905
4906function JSArgRec.getCalleObject: PJSObject;
4907begin
4908  Result := rec.calle.asObject;
4909end;
4910
4911function JSArgRec.GetIsConstructing: Boolean;
4912begin
4913  Result := rec.this.IsMagic;
4914end;
4915
4916function JSArgRec.getThis(cx: PJSContext): jsval;
4917begin
4918  if rec.this.IsPrimitive then
4919    result._l.asBits := JS_ComputeThis(cx, rec.calle) else
4920    result := rec.this;
4921end;
4922
4923function JSArgRec.getThisObject(cx: PJSContext): PJSObject;
4924begin
4925  Result := this[cx].asObject;
4926end;
4927
4928{ jsid }
4929
4930const
4931  JSID_TYPE_MASK = $7;
4932
4933function jsid.isString: Boolean;
4934begin
4935  Result := JSIdType(asBits and JSID_TYPE_MASK) = JSID_TYPE_STRING;
4936end;
4937
4938function jsid.asJSString: PJSString;
4939begin
4940{$ifdef WITHASSERT}
4941  Assert(isString);
4942{$endif}
4943  Result := PJSString(asBits);
4944end;
4945
4946{ jsval }
4947
4948const
4949{$ifdef CPU64}
4950  JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET         = JSVAL_TAG_NULL;
4951  JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET           = JSVAL_TAG_OBJECT;
4952
4953  JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET      = JSVAL_SHIFTED_TAG_UNDEFINED;
4954  JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET   = JSVAL_SHIFTED_TAG_OBJECT;
4955{$else}
4956  JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET         = JSVAL_TAG_NULL;
4957  JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET           = JSVAL_TAG_OBJECT;
4958  JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET              = JSVAL_TAG_INT32;
4959  JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET             = JSVAL_TAG_STRING;
4960{$endif}
4961
4962function jsval.getAsBoolean: Boolean;
4963begin
4964  {$ifdef WITHASSERT}
4965  assert(isBoolean);
4966  {$endif}
4967  {$ifdef  CPU64}
4968  Result := Boolean(_l.asBits and JSVAL_PAYLOAD_MASK)
4969  {$else}
4970  Result := Boolean(_l.s.payload.boo);
4971  {$endif}
4972end;
4973
4974function jsval.getAsDate(cx: PJSContext): TDateTime;
4975var oDate: PJSObject;
4976{$ifdef CONSIDER_TIME_IN_Z} // as defined in SyNode.inc
4977    ms: double;
4978    ms64: Int64;
4979    fval: jsval;
4980{$else}
4981    d, m, Y, h, mn, s, ml: Integer;
4982    v, fval: jsval;
4983  function GetIntFuncPropVal(funcName: PWideChar): Integer;
4984  begin
4985    Result := 0;
4986    if oDate.GetUCProperty(cx, pointer(funcName), Length(funcName), fval) then
4987      if oDate.CallFunctionValue(cx, fval, 0, nil, v)   then
4988        Result := v.asInteger;
4989  end;
4990{$endif}
4991begin
4992  oDate := getAsObject;
4993  if not oDate.isDate(cx) then
4994    raise ESMException.create('not a DateTime object');
4995{$ifdef CONSIDER_TIME_IN_Z}
4996  ms := 0;
4997  if oDate.CallFunctionName(cx, PCChar('getTime'), 0, nil, fval) then
4998    ms := fval.asDouble;
4999  if ms = 0 then
5000    raise ESMException.Create('JSDateToDateTime: no getTime() in Date object');
5001  ms64 := Trunc(ms);
5002  // W/O millisec: Result := IncMilliSecond(UnixDateDelta, ms64);
5003  Result := UnixMSTimeToDateTime(ms64);
5004{$else}
5005  d := GetIntFuncPropVal('getDate');
5006  m := GetIntFuncPropVal('getMonth') + 1; //WTF months start from 0
5007  Y := GetIntFuncPropVal('getFullYear');
5008  h := GetIntFuncPropVal('getHours');
5009  mn := GetIntFuncPropVal('getMinutes');
5010  s := GetIntFuncPropVal('getSeconds');
5011  ml := GetIntFuncPropVal('getMilliseconds');
5012  Result := EncodeDateTime(Y, m, d, h, mn, s, ml);
5013{$endif}
5014end;
5015
5016function jsval.getAsDouble: Double;
5017begin
5018  {$ifdef WITHASSERT}
5019  assert(isDouble);
5020  {$endif}
5021  Result := _l.asDouble;
5022end;
5023
5024function jsval.getAsInteger: Integer;
5025begin
5026  {$ifdef WITHASSERT}
5027  assert(isInteger);
5028  {$endif}
5029  {$ifdef CPU64}
5030  Result := int32(_l.asBits);
5031  {$else}
5032  Result := _l.s.payload.i32;
5033  {$endif}
5034end;
5035
5036function writeCallback(const buf: PCChar16; len: uint32; data: pointer): Boolean; cdecl;
5037begin
5038  TTextWriter(data).AddNoJSONEscapeW(pointer(buf),len);
5039  result := true;
5040end;
5041
5042procedure jsval.AddJSON(cx: PJSContext; W: TTextWriter);
5043var
5044//  voidVal: jsval;
5045  T: JSType;
5046begin
5047  if @self=nil then
5048    W.AddShort('null')
5049  else begin
5050    T := cx.TypeOfValue(self);
5051    case T of
5052      JSTYPE_VOID,
5053      JSTYPE_NULL:
5054        W.AddShort('null');
5055      JSTYPE_STRING:
5056        asJSString.ToJSONString(cx,W);
5057      JSTYPE_NUMBER:
5058        if isInteger then
5059          W.Add(asInteger) else
5060          W.AddDouble(asDouble);
5061      JSTYPE_BOOLEAN:
5062        W.Add(asBoolean);
5063      JSTYPE_OBJECT,
5064      JSTYPE_FUNCTION: begin
5065        if not Stringify(cx, nullObj, JSVAL_VOID, writeCallback, pointer(W)) then
5066          ;
5067      end
5068      else
5069        raise ESMException.CreateFmt('Unhandled AddJSON(%d)',[ord(T)]);
5070    end;
5071  end;
5072end;
5073
5074function jsval.getAsJson(cx: PJSContext): RawUTF8;
5075var W: TJSONWriter;
5076begin
5077  W := TJSONWriter.CreateOwnedStream;
5078  try
5079    AddJSON(cx,W);
5080    W.SetText(result);
5081  finally
5082    W.Free;
5083  end;
5084end;
5085
5086function jsval.getAsInt64: Int64;
5087begin
5088  if isInteger then
5089    result := asInteger else
5090  {$ifdef WITHASSERT}
5091  if not isDouble then
5092    raise ESMException.Create('jsval.getAsInt64!') else
5093  {$endif}
5094    result := trunc(asDouble);
5095end;
5096
5097function jsval.getAsObject: PJSObject;
5098{$ifdef  CPU64}
5099var  ptrBits: UInt64 absolute Result;
5100{$endif}
5101begin
5102  {$ifdef WITHASSERT}
5103  assert(isObject);
5104  {$endif}
5105  {$ifdef CPU64}
5106  ptrBits := _l.asBits and JSVAL_PAYLOAD_MASK;
5107  {$ifdef WITHASSERT}
5108  assert(ptrBits and 7 = 0);
5109  {$endif}
5110  {$else}
5111  Result := _l.s.payload.obj;
5112  {$endif}
5113end;
5114
5115function jsval.getIsBoolean: Boolean;
5116begin
5117  {$ifdef CPU64}
5118  Result := _l.asBits shr JSVAL_TAG_SHIFT = JSVAL_TAG_BOOLEAN;
5119  {$else}
5120  Result := _l.s.tag = JSVAL_TAG_BOOLEAN;
5121  {$endif}
5122end;
5123
5124function jsval.getIsDouble: Boolean;
5125begin
5126  {$ifdef CPU64}
5127  Result := _l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE
5128  {$else}
5129  Result := UInt32(_l.s.tag) <= UInt32(JSVAL_TAG_CLEAR)
5130  {$endif}
5131end;
5132
5133function jsval.getIsInteger: Boolean;
5134begin
5135  {$ifdef CPU64}
5136  Result := _l.asBits shr JSVAL_TAG_SHIFT = JSVAL_TAG_INT32;
5137  {$else}
5138  Result := _l.s.tag = JSVAL_TAG_INT32;
5139  {$endif}
5140end;
5141
5142function jsval.getIsNull: Boolean;
5143begin
5144  {$ifdef CPU64}
5145  Result := _l.asBits  = JSVAL_SHIFTED_TAG_NULL;
5146  {$else}
5147  Result := _l.s.tag = JSVAL_TAG_NULL;
5148  {$endif}
5149end;
5150
5151function jsval.getIsNumber: Boolean;
5152begin
5153  {$ifdef CPU64}
5154  Result := _l.asBits  < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
5155  {$else}
5156  {$ifdef WITHASSERT}
5157  assert(_l.s.tag <> JSVAL_TAG_CLEAR);
5158  {$endif}
5159  Result := (UInt32(_l.s.tag) <= UInt32(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
5160  {$endif}
5161end;
5162
5163function jsval.getIsObject: Boolean;
5164begin
5165  {$ifdef CPU64}
5166  {$ifdef WITHASSERT}
5167  Assert(_l.asBits shr JSVAL_TAG_SHIFT <= JSVAL_TAG_OBJECT);
5168  {$endif}
5169  Result := _l.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
5170  {$else}
5171  {$ifdef WITHASSERT}
5172  Assert(_l.s.tag <= JSVAL_TAG_OBJECT);
5173  {$endif}
5174  Result := (UInt32(_l.s.tag) >= UInt32(JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET));
5175  {$endif}
5176end;
5177
5178function jsval.getIsSimpleVariant(cx: PJSContext): Boolean;
5179var
5180  t: JSType;
5181begin
5182  t := ValType(cx);
5183  Result := (t = JSTYPE_VOID) or (t = JSTYPE_NULL) or (t = JSTYPE_STRING)
5184      or (t = JSTYPE_NUMBER) or (t = JSTYPE_BOOLEAN);
5185end;
5186
5187function jsval.getIsString: Boolean;
5188begin
5189  {$ifdef CPU64}
5190  Result := _l.asBits shr JSVAL_TAG_SHIFT = JSVAL_TAG_STRING;
5191  {$else}
5192  Result := _l.s.tag = JSVAL_TAG_STRING;
5193  {$endif}
5194end;
5195
5196function jsval.getIsVoid: Boolean;
5197begin
5198  {$ifdef CPU64}
5199  Result := _l.asBits = JSVAL_SHIFTED_TAG_UNDEFINED;
5200  {$else}
5201  Result := _l.s.tag = JSVAL_TAG_UNDEFINED;
5202  {$endif}
5203end;
5204
5205function jsval.getJSString: PJSString;
5206begin
5207  {$ifdef CPU64}
5208  Result := PJSString(_l.asBits and JSVAL_PAYLOAD_MASK);
5209  {$else}
5210  {$ifdef WITHASSERT}
5211  Assert(isString);
5212  {$endif}
5213  Result := _l.s.payload.str;
5214  {$endif}
5215end;
5216
5217function jsval.getPrivate: Pointer;
5218begin
5219  {$ifdef CPU64}
5220  {$ifdef WITHASSERT}
5221  Assert(_l.asBits and $8000000000000000 = 0);
5222  {$endif}
5223  Result := Pointer(_l.asBits shl 1);
5224  {$else}
5225  {$ifdef WITHASSERT}
5226  Assert(isDouble);
5227  {$endif}
5228  Result := _l.s.payload.ptr;
5229  {$endif}
5230end;
5231
5232function jsval.getSimpleVariant(cx: PJSContext): Variant;
5233var
5234  t: JSType;
5235begin
5236  t := ValType(cx);
5237  case t of
5238    JSTYPE_VOID:
5239      VarClear(result);
5240    JSTYPE_NULL:
5241      SetVariantNull(result);
5242//    JSTYPE_OBJECT:
5243// todo
5244    JSTYPE_STRING:
5245       getJSString.ToVariant(cx,result);
5246    JSTYPE_NUMBER:
5247      if getIsInteger then
5248        result := getAsInteger else
5249        result := getAsDouble;
5250    JSTYPE_BOOLEAN:
5251      result := getAsBoolean;
5252//    JSTYPE_FUNCTION:
5253// todo
5254    else
5255      raise ESMException.CreateFmt('Unhandled ToVariant(%d)',[ord(t)]);
5256  end;
5257
5258end;
5259
5260function jsval.IsMagic: Boolean;
5261begin
5262  {$IFDEF CPU64}
5263  Result := _l.asBits shr JSVAL_TAG_SHIFT = JSVAL_TAG_MAGIC;
5264  {$ELSE}
5265  Result := _l.s.tag = JSVAL_TAG_MAGIC;
5266  {$ENDIF}
5267end;
5268
5269function jsval.IsPrimitive: Boolean;
5270begin
5271  {$IFDEF CPU64}
5272  Result := _l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
5273  {$ELSE}
5274  Result := (UInt32(_l.s.tag) < UInt32(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
5275  {$ENDIF}
5276end;
5277
5278function doubleIsInt(Value: Double):boolean; {$ifdef HASINLINE}inline;{$endif}
5279var Value_int64:Int64 absolute Value;
5280    len: Int16;
5281begin
5282  len := (Value_int64 shr 52) and $7FF - $3FF;
5283  result := ((len >= 0) and (len < 31) and ((Value_int64 and (QWORD(1) shl (52 - len)-1)) = 0))
5284  or (Value_int64 = 0) or (Value_int64 = $C1E0000000000000);
5285end;
5286
5287function doubleToInt(Value: Double):Integer; {$ifdef HASINLINE}inline;{$endif}
5288var Value_int64:Int64 absolute Value;
5289    len: Smallint;
5290begin
5291  if Value_int64 = 0 then
5292    result := 0
5293  else begin
5294    len := (Value_int64 shr 52) and $7FF - $3FF;
5295    Result := (Value_int64 and $000FFFFFFFFFFFFF or $0010000000000000) shr (52-len);
5296    if (Value_int64 and $8000000000000000)<>0 then
5297      Result := -Result;
5298  end
5299end;
5300
5301procedure jsval.setAsBoolean(const Value: Boolean);
5302begin
5303  {$ifdef CPU64}
5304  _l.asBits := uint64(ord(Value)) or JSVAL_SHIFTED_TAG_BOOLEAN;
5305  {$else}
5306  _l.s.tag := JSVAL_TAG_BOOLEAN;
5307  _l.s.payload.boo := ord(Value);
5308  {$endif}
5309end;
5310
5311procedure jsval.setAsDate(cx: PJSContext; const Value: TDateTime);
5312var dmsec: double;
5313    unixTime: Int64;
5314  {$ifdef CONSIDER_TIME_IN_Z} // as defined in SyNode.inc
5315    oDate: PJSObject;
5316{$else}
5317    // this realisation is buggy - it ignores timezone rules change history
5318    // for server-side realisation the best solution is to use GMT time here
5319    ms: Word;
5320    STLocal, STUtc: TSystemTime;
5321    TZ: TTimeZoneInformation;
5322    AUTCDateTime: TDateTime;
5323{$endif}
5324begin
5325{$ifdef CONSIDER_TIME_IN_Z}
5326  unixTime := DateTimeToUnixMSTime(Value);
5327  dmsec := unixTime-(unixTime mod 1000);
5328  oDate := cx.NewDateObjectMsec(dmsec);
5329  if not oDate.IsDate(cx) then
5330    raise ESMException.CreateFmt('SetDateTime(%g): not a valid date',[Value]);
5331  setAsObject(oDate);
5332{$else}
5333  DateTimeToSystemTime(Value, STLocal);
5334  GetTimeZoneInformation(TZ);
5335  // use TzSpecificLocalTimeToSystemTime?
5336  TZ.Bias := -TZ.Bias;
5337  TZ.StandardBias := -TZ.StandardBias;
5338  TZ.DaylightBias := -TZ.DaylightBias;
5339  SystemTimeToTzSpecificLocalTime(@TZ, STLocal, STUtc);
5340  ms := STUtc.wMilliseconds;
5341  AUTCDateTime := SystemTimeToDateTime(STUtc);
5342  dmSec := DateTimeToUnixMSTime(AUTCDateTime) + ms;
5343  setAsObject(cx.NewDateObjectMsec(dmsec));
5344{$endif}
5345end;
5346
5347procedure jsval.setAsDouble(const Value: Double);
5348begin
5349  if doubleIsInt(Value) then
5350    asInteger := doubleToInt(Value)
5351  else begin
5352    _l.asDouble := Value;
5353    if ((_l.asBits and $7FF0000000000000) = $7FF0000000000000) and
5354       ((_l.asBits and $000FFFFFFFFFFFFF) <> $0000000000000000) then
5355      _l.asBits := JSVAL_NAN_impl; // canonize NaN
5356  end;
5357end;
5358
5359procedure jsval.setAsInteger(const Value: Integer);
5360
5361begin
5362  {$ifdef CPU64}
5363  _l.asBits := Value;
5364  _l.asBits := uint32(Value) or JSVAL_SHIFTED_TAG_INT32;
5365  {$else}
5366  _l.s.tag := JSVAL_TAG_INT32;
5367  _l.s.payload.i32 := Value;
5368  {$endif}
5369end;
5370
5371procedure jsval.setAsJson(cx: PJSContext; const Value: RawUTF8);
5372var tmp: RawUnicode;
5373    len: integer;
5374begin
5375  if Value='' then begin
5376    SetVoid;
5377  end else begin
5378    len := Utf8DecodeToRawUnicodeUI(Value,tmp);
5379    if not JS_ParseJSON(cx, pointer(tmp), len shr 1, self) then
5380    {$ifdef WITHASSERT}
5381      raise ESMException.Create('jsval.setAsJson!') else
5382    {$ELSE}
5383      SetVoid;
5384    {$endif}
5385  end;
5386end;
5387
5388procedure jsval.setAsInt64(const Value: Int64);
5389begin
5390  if (Value>=Low(integer)) and (Value<=High(integer)) then
5391    setAsInteger(Value) else
5392    setAsDouble(Value);
5393end;
5394
5395procedure jsval.setAsObject(const Value: PJSObject);
5396{$ifdef CPU64}
5397var objBits: UInt64 absolute Value;
5398{$endif}
5399begin
5400  {$ifdef CPU64}
5401  {$ifdef WITHASSERT}
5402  Assert(objBits shr JSVAL_TAG_SHIFT = 0);
5403  {$endif}
5404  _l.asBits := QWord(objBits or JSVAL_SHIFTED_TAG_OBJECT);
5405  {$else}
5406  if Value<>nil then begin
5407    _l.s.tag := JSVAL_TAG_OBJECT;
5408    _l.s.payload.obj := Value;
5409  end else
5410    _l.asBits := JSVAL_NULL_impl;
5411  {$endif}
5412end;
5413
5414procedure jsval.setJSString(const Value: PJSString);
5415{$ifdef CPU64}
5416var strBits: UInt64 absolute Value;
5417{$endif}
5418begin
5419  {$ifdef CPU64}
5420  {$ifdef WITHASSERT}
5421  Assert(strBits shr JSVAL_TAG_SHIFT = 0);
5422  {$endif}
5423  _l.asBits := strBits or JSVAL_SHIFTED_TAG_STRING;
5424  {$else}
5425  {$ifdef WITHASSERT}
5426  assert(str<>nil) ;
5427  {$endif}
5428  _l.s.tag := JSVAL_TAG_STRING;
5429  _l.s.payload.str := Value;
5430  {$endif}
5431end;
5432
5433procedure jsval.setNull;
5434begin
5435  _l.asBits := JSVAL_NULL_impl;
5436end;
5437
5438procedure jsval.setPrivate(const Value: Pointer);
5439{$ifdef CPU64}
5440var ptrBits: UInt64 absolute Value;
5441{$endif}
5442begin
5443  {$ifdef CPU64}
5444  {$ifdef WITHASSERT}
5445  Assert(ptrBits and 1 = 0);
5446  {$endif}
5447  _l.asBits := ptrBits shr 1;
5448  {$ifdef WITHASSERT}
5449  assert(isDouble);
5450  {$endif}
5451  {$else}
5452  {$ifdef WITHASSERT}
5453  assert((uint32(ptr) and 1) = 0);
5454  {$endif}
5455  _l.s.tag := JSValueTag(0);
5456  _l.s.payload.ptr := Value;
5457  {$ifdef WITHASSERT}
5458  assert(isDouble);
5459  {$endif}
5460  {$endif}
5461end;
5462
5463procedure jsval.setSimpleVariant(cx: PJSContext; const Value: Variant);
5464begin
5465  with TVarData(Value) do
5466  case VType of
5467    varNull: setNull;
5468    varEmpty: setVoid;
5469    varBoolean: setAsBoolean(VBoolean);
5470    varSmallint: setAsInteger(VSmallInt);
5471    {$ifndef DELPHI5OROLDER}
5472    varShortInt: setAsInteger(VShortInt);
5473    varWord: setAsInteger(VWord);
5474    varLongWord: setAsInt64(VLongWord);
5475    {$endif}
5476    varByte: setAsInteger(VByte);
5477    varInteger: setAsInteger(VInteger);
5478    {$ifdef FPC}varQword,{$endif}
5479    varInt64: setAsInt64(VInt64);
5480
5481    varSingle: setAsDouble(VSingle);
5482    varDouble: setAsDouble(VDouble);
5483    varCurrency: setAsDouble(VCurrency);
5484    varDate: setAsDate(cx, VDate);
5485    varOleStr: setJSString(cx.NewJSString(WideString(VAny)));
5486    varString: setJSString(cx.NewJSString(VAny,length(RawByteString(VAny)),
5487    {$ifndef UNICODE}   CP_UTF8));
5488    {$else}             StringCodePage(RawByteString(VAny))));
5489    varUString: setJSString(cx.NewJSString(UnicodeString(VAny)));
5490    {$endif}
5491  else
5492    if VType=varByRef or varVariant then
5493      setSimpleVariant(cx,PVariant(VPointer)^) else
5494    if VType=varByRef or varOleStr then
5495      setJSString(cx.NewJSString(PWideString(VAny)^)) else
5496    {$ifdef UNICODE}
5497    if VType=varByRef or varUString then
5498      setJSString(cx.NewJSString(PUnicodeString(VAny)^)) else
5499    {$endif}
5500      raise ESMException.CreateFmt('Unhandled variant type %d',[VType]);
5501  end;
5502end;
5503
5504procedure jsval.setVoid;
5505begin
5506  _l.asBits := JSVAL_VOID_impl;
5507end;
5508
5509function jsval.Stringify(cx: PJSContext; var replacer: PJSObject;
5510  space: jsval; callback: JSONWriteCallback; data: pointer): Boolean;
5511begin
5512  with TSynFPUException.ForLibraryCode do
5513    Result := JS_Stringify(cx, Self, replacer, space, callback, data);
5514end;
5515
5516function jsval.toSource(cx: PJSContext): PJSString;
5517begin
5518  Result := JS_ValueToSource(cx, self);
5519end;
5520
5521function jsval.ValType(cx: PJSContext): JSType;
5522begin
5523  Result := cx.TypeOfValue(self);
5524end;
5525
5526class function jsval.NullValue: jsval;
5527begin
5528  Result.setNull();
5529end;
5530
5531class function jsval.Int32Value(v: integer): jsval;
5532begin
5533  Result.asInteger := v;
5534end;
5535
5536class function jsval.BooleanValue(v: boolean): jsval;
5537begin
5538  Result.asBoolean := v;
5539end;
5540
5541class function jsval.TrueValue: jsval;
5542begin
5543  Result.asBoolean := True;
5544end;
5545
5546class function jsval.FalseValue: jsval;
5547begin
5548  Result.asBoolean := False;
5549end;
5550
5551class function jsval.DoubleValue(v: double): jsval;
5552begin
5553  Result.asDouble := v;
5554end;
5555
5556class function jsval.StringValue(v: PJSString): jsval;
5557begin
5558  Result.asJSString := v;
5559end;
5560
5561class function jsval.ObjectValue(v: PJSObject): jsval;
5562begin
5563  Result.asObject := v;
5564end;
5565
5566class function jsval.Int64Value(v: Int64): jsval;
5567begin
5568  Result.asInt64 := v;
5569end;
5570
5571function SimpleVariantToJSval(cx: PJSContext; val: Variant): jsval;
5572begin
5573  Result.asSimpleVariant[cx] := val;
5574end;
5575
5576initialization
5577  Latin1AnsiConvert := TSynAnsiConvert.Engine(CODEPAGE_LATIN1);
5578end.