Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | upgraded SpiderMonkey engine into revision 24 (pavel did write a custom C wrapper around the original C++ code) - also updated http://synopse.info/files/synsm.7z to contain the corresponding binaries - Thanks again Pavel (mpv) for the contribution! |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
687f12d548e60b2e44603ac9d421423c |
User & Date: | User 2014-04-21 07:49:03 |
2014-04-21
| ||
08:20 | updated SMAPI.pas comments for better generated documentation - also replaced CString by AnsiString check-in: f6b8f90445 user: User tags: trunk | |
07:49 | upgraded SpiderMonkey engine into revision 24 (pavel did write a custom C wrapper around the original C++ code) - also updated http://synopse.info/files/synsm.7z to contain the corresponding binaries - Thanks again Pavel (mpv) for the contribution! check-in: 687f12d548 user: User tags: trunk | |
2014-04-19
| ||
07:13 | ensure TSQLPropInfoRTTIObject.SetValue() and TSQLPropInfoRTTIVariant.SetValue() will use a temporary copy of the JSON content before parsing it: it will allow to re-parse a TSQLRecord object e.g. via FillRow(aIndex) more than once check-in: 899e5aa900 user: User tags: trunk | |
Changes to SQLite3/Documentation/Synopse SQLite3 Framework.pro.
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
....
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
|
For instance, here is how a customer data is retrieved from a {\f1\fs20 GET} method: $$ <Customer> $$ <ID>1234</ID> $$ <Name>Dupond</Name> $$ <Address>Tree street</Address> $$</Customer> $$ Below is a simple JSON snippet for creating a new customer record with name and address: $ {Customer: {"Name":"Dupont", "Address":"Tree street"}} As a result to this data transmitted with a {\f1\fs20 POST} command, the RESTful server will return the just-created ID. See @2@ for the reasons why in {\i mORMot}, we prefer to use JSON format. : Stateless Every request should be an independent request so that we can scale up using load balancing techniques. Independent request means with the data also send the state of the request so that the server can carry forward the same from that level to the next level. See @15@ for more details. : RESTful mORMot ................................................................................ - Handle {\i JavaScript} or {\i Delphi} objects as @32@ @2@, ready to be published or consumed via @6@ remote access. : SpiderMonkey integration : A powerful JavaScript engine {\i @**SpiderMonkey@}, the Mozilla {\i @*JavaScript@} engine, can be embedded in your {\i mORMot} application. It could be used on client side, within a Delphi application (e.g. for reporting), but the main interest of it may be on the server side. The word {\i JavaScript} may bring to mind features such as event handlers (like {\f1\fs20 onclick}), {\f1\fs20 DOM} objects, {\f1\fs20 window.open}, and {\f1\fs20 XMLHttpRequest}.\line But all of these features are actually not provided by the {\i SpiderMonkey} engine itself. {\i SpiderMonkey} provides a few core {\i JavaScript} data types�numbers, strings, Arrays, Objects, and so on�and a few methods, such as {\f1\fs20 Array.push}. It also makes it easy for each application to expose some of its own objects and functions to {\i JavaScript} code. Browsers expose DOM objects. Your application will expose objects that are relevant for the kind of scripts you want to write. It is up to the application developer to decide what objects and methods are exposed to scripts. : Direct access to the SpiderMonkey API The {\f1\fs20 SynSMAPI.pas} unit is a tuned conversion of the {\i SpiderMonkey} API, providing full {\i ECMAScript 5} support and {\i JIT}.\line You could take a look at @http://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey for a full description of this low-level API. But the {\f1\fs20 SynSM.pas} unit will encapsulate most of it into higher level Delphi classes and structures (including a custom {\f1\fs20 variant} type), so you probably won't need to use {\f1\fs20 SynSMAPI.pas} directly in your code: |%25%75 |\b Type|Description\b0 |{\f1\fs20 TSMEngineManager}|main access point to the {\i SpiderMonkey} per-thread scripting engines |{\f1\fs20 TSMEngine}|implements a Thread-Safe {\i JavaScript} engine instance |{\f1\fs20 TSMObject}|wrap a {\i JavaScript} object and its execution context |{\f1\fs20 TSMValue}|wrap a {\i JavaScript} value, and interfaces it with Delphi types |
|
|
|
|
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
....
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
|
For instance, here is how a customer data is retrieved from a {\f1\fs20 GET} method: $$ <Customer> $$ <ID>1234</ID> $$ <Name>Dupond</Name> $$ <Address>Tree street</Address> $$</Customer> $$ Below is a simple JSON snippet for creating a new customer record with name and address (since we create a new record, here we named him "Dupond" - with an ending D - not "Dupont"): $ {"Customer": {"Name":"Dupond", "Address":"Tree street"}} As a result to this data transmitted with a {\f1\fs20 POST} command, the RESTful server will return the just-created ID. See @2@ for the reasons why in {\i mORMot}, we prefer to use JSON format. : Stateless Every request should be an independent request so that we can scale up using load balancing techniques. Independent request means with the data also send the state of the request so that the server can carry forward the same from that level to the next level. See @15@ for more details. : RESTful mORMot ................................................................................ - Handle {\i JavaScript} or {\i Delphi} objects as @32@ @2@, ready to be published or consumed via @6@ remote access. : SpiderMonkey integration : A powerful JavaScript engine {\i @**SpiderMonkey@}, the Mozilla {\i @*JavaScript@} engine, can be embedded in your {\i mORMot} application. It could be used on client side, within a Delphi application (e.g. for reporting), but the main interest of it may be on the server side. The word {\i JavaScript} may bring to mind features such as event handlers (like {\f1\fs20 onclick}), {\f1\fs20 DOM} objects, {\f1\fs20 window.open}, and {\f1\fs20 XMLHttpRequest}.\line But all of these features are actually not provided by the {\i SpiderMonkey} engine itself. {\i SpiderMonkey} provides a few core {\i JavaScript} data types�numbers, strings, Arrays, Objects, and so on�and a few methods, such as {\f1\fs20 Array.push}. It also makes it easy for each application to expose some of its own objects and functions to {\i JavaScript} code. Browsers expose DOM objects. Your application will expose objects that are relevant for the kind of scripts you want to write. It is up to the application developer to decide what objects and methods are exposed to scripts. : Direct access to the SpiderMonkey API The {\f1\fs20 SynSMAPI.pas} unit is a tuned conversion of the {\i SpiderMonkey} API, providing full {\i ECMAScript 5} support and {\i JIT}. The {\i SpiderMonkey} revision 24 engine is included, with a custom C wrapper around the original C++ code. \line You could take a look at @http://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey for a full description of this low-level API. But the {\f1\fs20 SynSM.pas} unit will encapsulate most of it into higher level Delphi classes and structures (including a custom {\f1\fs20 variant} type), so you probably won't need to use {\f1\fs20 SynSMAPI.pas} directly in your code: |%25%75 |\b Type|Description\b0 |{\f1\fs20 TSMEngineManager}|main access point to the {\i SpiderMonkey} per-thread scripting engines |{\f1\fs20 TSMEngine}|implements a Thread-Safe {\i JavaScript} engine instance |{\f1\fs20 TSMObject}|wrap a {\i JavaScript} object and its execution context |{\f1\fs20 TSMValue}|wrap a {\i JavaScript} value, and interfaces it with Delphi types |
Changes to SQLite3/Samples/22 - JavaScript HTTPApi web server/JSHttpApiServer.dpr.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/// sample program which will serve content on http://localhost:888/root
// - in case of *.md file, execute Showdown template engine in JavaScript
program JSHttpApiServer;
{
-------------------------------------------------------------------------
Download the SpiderMonkey library at http://synopse.info/files/synsm.7z
and put the mozjs.dll and nspr4.dll files with your JSHttpApiServer.exe
-------------------------------------------------------------------------
}
{$APPTYPE CONSOLE}
{$ifdef WIN64}
begin
writeln('SpiderMonkey is not handled in 64 bit mode yet');
|
| | | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/// sample program which will serve content on http://localhost:888/root // - in case of *.md file, execute Showdown template engine in JavaScript program JSHttpApiServer; { --------------------------------------------------------------------------- Download the SpiderMonkey library at http://synopse.info/files/synsm.7z and put mozjs-24.dll and libnspr4.dll files with your JSHttpApiServer.exe --------------------------------------------------------------------------- } {$APPTYPE CONSOLE} {$ifdef WIN64} begin writeln('SpiderMonkey is not handled in 64 bit mode yet'); |
Changes to SynSM.pas.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 .. 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 .. 89 90 91 92 93 94 95 96 97 98 99 100 101 102 ... 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 ... 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 ... 582 583 584 585 586 587 588 589 590 591 592 593 594 595 ... 636 637 638 639 640 641 642 643 644 645 646 647 648 649 ... 653 654 655 656 657 658 659 660 661 662 663 664 665 666 ... 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 ... 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 ... 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 .... 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 .... 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 .... 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 .... 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 .... 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 .... 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 .... 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 .... 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 .... 2024 2025 2026 2027 2028 2029 2030 2031 2032 |
The Initial Developer of the Original Code is Pavel Mashlyakovsky. Portions created by the Initial Developer are Copyright (C) 2014 the Initial Developer. All Rights Reserved. Contributor(s): - Arnaud Bouchez Alternatively, the contents of this file may be used under the terms of either the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to ................................................................................ --------------------------------------------------------------------------- Download the SpiderMonkey library at http://synopse.info/files/synsm.7z ! --------------------------------------------------------------------------- Version 1.18 - initial release. Use SpiderMonkey 1.8.5 - add TSMObject.defineNativeMethod - add JSError procedure for Exception handling inside of JSNative function - enhanced multi thread process - add TSMEngine.MaybeGarbageCollect method } {$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64 OWNNORMTOUPPER {$I SynSM.inc} // define SM_DEBUG JS_THREADSAFE CONSIDER_TIME_IN_Z interface ................................................................................ ESMException = class(Exception); {$M+} TSMEngineManager = class; {$M-} TSMEngine = class; /// just a wrapper around jsval API type, to be used with our object wrappers // - SpiderMonkey jsval type can be directly casted to this type via TSMValue(jsval) // - note that some methods expect an execution context to be supplied as // parameter, as soon as it contains a non primitive type (double/integer) TSMValue = object protected ................................................................................ // - here the method name is specified as SynUnicode // - func if reference to function with JSNative signature // - nargs is function argument count // - actually this method creates a JSFunction and assing its value to // ! obj[methodName] // - to add a global function, define it into the "global" object - i.e. call // ! TSMEngine.GlobalObject.DefineNativeMethod() procedure DefineNativeMethod(const methodName: SynUnicode; func: JSNative; nargs: uintN); overload; /// add JSNative compatible function into JS object // - here the method name is specified as AnsiString // - func if reference to function with JSNative signature // - nargs is function argument count procedure DefineNativeMethod(const methodName: AnsiString; func: JSNative; nargs: uintN); overload; /// check object property does exist (including prototype chain lookup) function HasProperty(const propName: SynUnicode): Boolean; /// Determine whether a property is physically present on a object // - JavaScript equivalent of // ! Object.hasOwnProperty(propName) function HasOwnProperty(const propName: SynUnicode): Boolean; ................................................................................ // - contains also one "global" JavaScript object. From script it is // accessible via "global." (in browser, this is the "window." object) // - set SpiderMonkey error reporter and store last SpiderMonkey error in // LastError property TSMEngine = class protected frt: PJSRuntime; fCx: PJSContext; fNativeMethod: TSMEngineMethodEventDynArray; fNativeMethods: TDynArrayHashed; fNativeMethodCount: integer; FManager: TSMEngineManager; FGlobal: variant; FGlobalObject: TSMObject; FEngineContentVersion: Cardinal; FStringFinalizerID: intN; FThreadID: DWORD; FLastErrorMsg: RawUTF8; FLastErrorFileName: RawUTF8; FLastErrorLine: integer; FErrorExist: boolean; function InternalRegisterMethod(obj: PJSObject; const MethodName: SynUnicode; const Event: TMethod; Kind: TSMEngineMethodEventKind; ArgumentsCount: integer): PJSFunction; /// called from SpiderMonkey callback. Do not raise exception here // instead use CheckJSError metod after JSAPI compile/evaluate call procedure DoProcessJSError(errMsg: PCChar; report: PJSErrorReport); virtual; public /// create one threadsafe JavaScript Engine instance // - initialize internal JSRuntime, JSContext, and global objects and // standard JavaScript classes // - do not create Engine directly via this constructor, but instead call // TSMEngineManager.ThreadSafeEngine constructor Create(aManager: TSMEngineManager); virtual; ................................................................................ // as in JavaScript: // ! var obj = {} procedure NewObject(out newobj: TSMObject); overload; /// create new JavaScript object with prototype // - JavaScript equivalent of // ! {}.__proto__ := prototype; procedure NewObject(const prototype: TSMObject; out newobj: TSMObject); overload; /// converts a JavaScript value into a JavaScript object procedure MakeObject(const value: TSMValue; out obj: TSMObject); overload; {$ifdef HASINLINE}inline;{$endif} /// converts a JavaScript low-level value into a JavaScript object procedure MakeObject(const value: jsval; out obj: TSMObject); overload; /// converts a JavaScript low-level object into a JavaScript object procedure MakeObject(jsobj: PJSObject; out obj: TSMObject); overload; ................................................................................ property GlobalObject: TSMObject read FGlobalObject; /// access to the associated global object as low-level PJSObject property GlobalObj: PJSObject read FGlobalObject.fobj; /// access to the associated execution context property cx: PJSContext read fCx; /// access to the associated execution runtime property rt: PJSRuntime read frt; /// internal version number of engine scripts // - used in TSMEngine.ThreadSafeEngine to determine if context is up to // date, in order to trigger on-the-fly reload of scripts without the need // if restarting the application // - caller must change this parameter value e.g. in case of changes in // the scripts folder in an HTTP server ................................................................................ property LastErrorMsg: RawUTF8 read FLastErrorMsg; /// last error source code line number triggered during JavaScript execution property LastErrorLine: integer read FLastErrorLine; /// last error file name triggered during JavaScript execution property LastErrorFileName: RawUTF8 read FLastErrorFileName; /// TRUE if an error was triggered during JavaScript execution property ErrorExist: boolean read FErrorExist; end; /// prototype of SpideMonkey notification callback method TEngineEvent = procedure(const Engine: TSMEngine) of object; /// main access point to the SpiderMonkey per-thread scripting engines ................................................................................ var /// define the TSynLog class used for logging for all our SynSM related units // - you may override it with TSQLLog, if available from mORMot.pas // - since not all exceptions are handled specificaly by this unit, you // may better use a common TSynLog class for the whole application or module SynSMLog: TSynLogClass=TSynLog; implementation uses Math; //DateUtils; const jsglobal_class: JSClass = (name: 'global'; flags: JSCLASS_HAS_PRIVATE or JSCLASS_GLOBAL_FLAGS { or JSCLASS_NEW_RESOLVE }; addProperty: JS_PropertyStub; delProperty: JS_PropertyStub; getProperty: JS_PropertyStub; setProperty: JS_StrictPropertyStub; enumerate: JS_EnumerateStub; resolve: JS_ResolveStub; convert: JS_ConvertStub; finalize: JS_FinalizeStub); /// handle errors from JavaScript. Just call DoProcessJSError of corresponding TSMEngine // to set TSMEngine error properties procedure ErrorReporter(cx: PJSContext; pErrMsg: PCChar; report: PJSErrorReport); cdecl; begin TSMEngine(cx.PrivateData).DoProcessJSError(pErrMsg, report) end; ................................................................................ if JS_IsExceptionPending(cx)=JS_FALSE then // raise only if this is the first exception in chain if aException is EOutOfMemory then JS_ReportOutOfMemory(cx) else JS_ReportError(cx, PCchar(AnsiString(aException.Message)+AnsiString(aContext))); end; { TSMEngine } // do nothing here procedure ExternalStringFinalizer(cx: PJSContext; obj: PJSString); cdecl; begin {} end; constructor TSMEngine.Create(aManager: TSMEngineManager); begin if aManager = nil then raise ESMException.Create('No manager provided'); fNativeMethods.Init(TypeInfo(TSMEngineMethodEventDynArray), fNativeMethod,HashPointer,SortDynArrayPointer,nil,@fNativeMethodCount); TSynFPUException.ForLibraryCode; FManager := aManager; FEngineContentVersion := FManager.ContentVersion; frt := JS_NewRuntime(FManager.MaxPerEngineMemory); if frt = nil then raise ESMException.Create('Create runtime: out of memory'); fCx := JS_NewContext(rt, STACK_CHUNK_SIZE); if fCx = nil then raise ESMException.Create('JSContext create'); fCx.Options := [{jsoStrict, jsoWError, }jsoVarObjFix, jsoXML, jsoRelimit, jsoObsoleteJIT, jsoMethodJIT]; fCx.Version := JSVERSION_LATEST; FStringFinalizerID := JS_AddExternalStringFinalizer(ExternalStringFinalizer); JS_SetContextPrivate(cx, self); JS_SetErrorReporter(cx, ErrorReporter); FGlobalObject.fCx := cx; FGlobalObject.fObj := JS_NewCompartmentAndGlobalObject(cx,@jsglobal_class,nil); if GlobalObj = nil then raise ESMException.Create('Create global object'); if JS_InitStandardClasses(cx, GlobalObj)<>JS_TRUE then raise ESMException.Create('InitStandardClasses'); FGlobalObject.DefineProperty('global', GlobalObject.AsSMValue, [jspEnumerate,jspPermanent,jspReadOnly]); TSMVariantData(FGlobal).Init(FGlobalObject); end; destructor TSMEngine.Destroy; begin inherited Destroy; TSynFPUException.ForLibraryCode; JS_RemoveExternalStringFinalizer(ExternalStringFinalizer); cx^.Destroy; rt^.Destroy; end; procedure TSMEngine.DoProcessJSError(errMsg: PCChar; report: PJSErrorReport); const PATTERN: PUTF8Char = '[JSError %] % (%): %'; begin FErrorExist := True; if report^.filename = nil then FLastErrorFileName := '(w/o name)' else FLastErrorFileName := CurrentAnsiConvert.AnsiBufferToRawUTF8( report^.filename,StrLen(pointer(report^.filename))); FLastErrorLine := report^.lineno; if report^.ucmessage=nil then FLastErrorMsg := FormatUTF8(PATTERN,[report^.errorNumber,FLastErrorFileName, FLastErrorLine,errMsg]) else FLastErrorMsg := FormatUTF8(PATTERN,[report^.errorNumber,FLastErrorFileName, FLastErrorLine,PWideChar(report^.ucmessage)]); end; procedure TSMEngine.CheckJSError(res: JSBool); begin if FErrorExist then begin SynSMLog.Add.Log(sllError, FLastErrorMsg); raise ESMException.Create(UTF8ToString(FLastErrorMsg)); end; if res=JS_FALSE then begin SynSMLog.Add.Log(sllError, 'Error compiling script %', FLastErrorFileName); raise ESMException.CreateFmt('Error compiling script "%s". Line %d', ................................................................................ end; end; procedure TSMEngine.ClearLastError; begin JS_ClearPendingException(cx); FErrorExist := False; end; procedure TSMEngine.GarbageCollect; begin JS_GC(cx); end; procedure TSMEngine.MaybeGarbageCollect; begin JS_MaybeGC(cx); end; ................................................................................ procedure TSMEngine.NewObject(const prototype: TSMObject; out newobj: TSMObject); begin newobj.fCx := cx; newobj.fObj := JS_NewObject(cx, nil{class}, prototype.obj, nil{parent}); if newobj.fObj=nil then raise ESMException.Create('NewObject(prototype)'); end; procedure TSMEngine.MakeObject(const value: TSMValue; out obj: TSMObject); begin MakeObject(value.FValue,obj); end; procedure TSMEngine.MakeObject(const value: jsval; out obj: TSMObject); ................................................................................ JSVAL_TO_STRING(FValue).ToVariant(cx,result); JSTYPE_NUMBER: if JSVAL_IS_INT(FValue) then result := JSVAL_TO_INT(FValue) else result := JSVAL_TO_DOUBLE(FValue); JSTYPE_BOOLEAN: result := JSVAL_TO_BOOLEAN(FValue)=JS_TRUE; JSTYPE_FUNCTION, JSTYPE_XML: result := TransformToSynUnicode(cx); else raise ESMException.CreateFmt('Unhandled ToVariant(%d)',[ord(ValType(cx))]); end; end; procedure TSMValue.SetVariant(cx: PJSContext; const Value: Variant); ................................................................................ begin FValue := STRING_TO_JSVAL(cx^.NewJSString(aStr)); end; procedure TSMValue.SetNativeString(cx: PJSContext; const aStr: SynUnicode); begin FValue := STRING_TO_JSVAL(JS_NewExternalString(cx, pointer(aStr), length(aStr), TSMEngine(cx.PrivateData).FStringFinalizerID)); end; function TSMValue.ToDateTime(cx: PJSContext): TDateTime; var oDate: PJSObject; {$ifdef CONSIDER_TIME_IN_Z} // as defined in SynSM.inc ms: double; ms64: Int64; ................................................................................ ml := GetIntFuncPropVal('getMilliseconds'); Result := EncodeDateTime(Y, m, d, h, mn, s, ml); {$endif} end; procedure TSMValue.SetDateTime(cx: PJSContext; const Value: TDateTime); var dmsec: double; {$ifndef CONSIDER_TIME_IN_Z} // as defined in SynSM.inc // this realisation is buggy - it ignores timezone rules change history // for server-side realisation the best solution is to use GMT time here ms: Word; STLocal, STUtc: TSystemTime; TZ: TTimeZoneInformation; AUTCDateTime: TDateTime; {$endif} begin {$ifdef CONSIDER_TIME_IN_Z} dmsec := DateTimeToUnixMSTime(Value); FValue := JS_NewDateObjectMsec(cx, dmsec).ToJSValue; {$else} DateTimeToSystemTime(Value, STLocal); GetTimeZoneInformation(TZ); // use TzSpecificLocalTimeToSystemTime? TZ.Bias := -TZ.Bias; TZ.StandardBias := -TZ.StandardBias; TZ.DaylightBias := -TZ.DaylightBias; ................................................................................ inc(buf); end; RawUnicodeToUtf8(name,buf-name,result); end; function writeCallback(const buf: Pjschar; len: uint32; data: pointer): JSBool; cdecl; begin TTextWriter(data).AddNoJSONEscapeW(pointer(buf),len shr 1); result := JS_TRUE; end; procedure TSMValue.AddJSON(cx: PJSContext; W: TTextWriter); begin if @self=nil then W.AddShort('null') else ................................................................................ JSTYPE_NUMBER: if JSVAL_IS_INT(FValue) then W.Add(JSVAL_TO_INT(FValue)) else W.Add(JSVAL_TO_DOUBLE(FValue)); JSTYPE_BOOLEAN: W.AddString(JSON_BOOLEAN[JSVAL_TO_BOOLEAN(FValue)=JS_TRUE]); JSTYPE_OBJECT, JSTYPE_FUNCTION, JSTYPE_XML: JS_Stringify(cx, @FValue, nil, JSVAL_NULL, writeCallback, pointer(W)); else raise ESMException.CreateFmt('Unhandled AddJSON(%d)',[ord(ValType(cx))]); end; end; function TSMValue.ToJSON(cx: PJSContext): RawUTF8; ................................................................................ lineNo: Cardinal; out result: TSMValue); var r: JSBool; eng: TSMEngine; begin TSynFPUException.ForLibraryCode; eng := Engine; eng.ClearLastError; r := JS_EvaluateUCScript(cx, obj, pointer(script), length(script), pointer(scriptName), lineNo, Result.FValue); eng.CheckJSError(r); end; procedure TSMObject.RunMethod(const methodName: CString; const argv: SMValArray; out rval: TSMValue); begin TSynFPUException.ForLibraryCode; Engine.CheckJSError(JS_CallFunctionName(cx, obj, pointer(methodName), Length(argv), pointer(argv), rval.FValue)); end; procedure TSMObject.RunMethod(const methodName: CString; const argv: array of const; out rval: TSMValue); var args: SMValArray; a: integer; begin ................................................................................ procedure TSMObject.UnRoot; begin if obj<>nil then JS_RemoveObjectRoot(cx, @obj); end; procedure TSMObject.DefineNativeMethod(const methodName: SynUnicode; func: JSNative; nargs: uintN); begin if JS_DefineUCFunction(cx, obj, Pjschar(methodName), Length(methodName), func, nargs, JSPROP_ENUMERATE)=nil then raise ESMException.CreateFmt('Impossible to define native method "%s"',[methodName]); end; procedure TSMObject.DefineNativeMethod(const methodName: AnsiString; func: JSNative; nargs: uintN); begin if JS_DefineFunction(cx, obj, PCChar(methodName), func, nargs, JSPROP_ENUMERATE)=nil then raise ESMException.CreateFmt('Impossible to define native method "%s"',[methodName]); end; function TSMObject.Parent: TSMObject; begin result.fCx := cx; if obj=nil then result.fObj := nil else result.fObj := JS_GetParent(cx, obj); end; function TSMObject.Prototype: TSMObject; begin result.fCx := cx; if obj=nil then result.fObj := nil else result.fObj := JS_GetPrototype(cx, obj); end; function TSMObject.GetPrivate: pointer; begin if obj=nil then result := nil else result := JS_GetPrivate(cx, obj); end; procedure TSMObject.SetPrivate(const Value: pointer); begin if obj<>nil then JS_SetPrivate(cx, obj, Value); end; function TSMObject.GetPrivateData(expectedClass: PJSClass): pointer; begin if obj=nil then result := nil else result := JS_GetInstancePrivate(cx, obj, expectedClass, nil); ................................................................................ VObject.fCx := aCx; VObject.fObj := aObj; end; initialization Assert(sizeof(TSMVariantData)=sizeof(variant)); end. |
> | > | > | | | | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | | | | | | | > > > > > > > | > > > > > > > | < < | > > | > > | | | | | | > | | > > > > | | > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > | < | | > > | > > > | | < > | | > > > | | > > | | > > | > | | | > | > | | | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > | > > > > > > > > | > > > < < |
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 .. 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 .. 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 ... 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 ... 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 ... 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 ... 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 ... 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 ... 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 ... 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 .... 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 .... 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 .... 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 .... 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 .... 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 .... 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 .... 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 .... 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 .... 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 .... 2313 2314 2315 2316 2317 2318 2319 |
The Initial Developer of the Original Code is Pavel Mashlyakovsky. Portions created by the Initial Developer are Copyright (C) 2014 the Initial Developer. All Rights Reserved. Contributor(s): - Arnaud Bouchez - Vadim Orel Alternatively, the contents of this file may be used under the terms of either the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to ................................................................................ --------------------------------------------------------------------------- Download the SpiderMonkey library at http://synopse.info/files/synsm.7z ! --------------------------------------------------------------------------- Version 1.18 - initial release. Use SpiderMonkey 24 - add TSMObject.defineNativeMethod - add JSError procedure for Exception handling inside of JSNative function - enhanced multi thread process - add TSMEngine.MaybeGarbageCollect method - add timeout Framework } {$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64 OWNNORMTOUPPER {$I SynSM.inc} // define SM_DEBUG JS_THREADSAFE CONSIDER_TIME_IN_Z interface ................................................................................ ESMException = class(Exception); {$M+} TSMEngineManager = class; {$M-} TSMEngine = class; /// just a wrapper around jsval API type, to be used with our object wrappers // - SpiderMonkey jsval type can be directly casted to this type via TSMValue(jsval) // - note that some methods expect an execution context to be supplied as // parameter, as soon as it contains a non primitive type (double/integer) TSMValue = object protected ................................................................................ // - here the method name is specified as SynUnicode // - func if reference to function with JSNative signature // - nargs is function argument count // - actually this method creates a JSFunction and assing its value to // ! obj[methodName] // - to add a global function, define it into the "global" object - i.e. call // ! TSMEngine.GlobalObject.DefineNativeMethod() function DefineNativeMethod(const methodName: SynUnicode; func: JSNative; nargs: uintN; attrs: TJSPropertyAttrs=[jspEnumerate]): PJSFunction; overload; /// add JSNative compatible function into JS object // - here the method name is specified as AnsiString // - func if reference to function with JSNative signature // - nargs is function argument count function DefineNativeMethod(const methodName: AnsiString; func: JSNative; nargs: uintN; attrs: TJSPropertyAttrs=[jspEnumerate]): PJSFunction; overload; /// check object property does exist (including prototype chain lookup) function HasProperty(const propName: SynUnicode): Boolean; /// Determine whether a property is physically present on a object // - JavaScript equivalent of // ! Object.hasOwnProperty(propName) function HasOwnProperty(const propName: SynUnicode): Boolean; ................................................................................ // - contains also one "global" JavaScript object. From script it is // accessible via "global." (in browser, this is the "window." object) // - set SpiderMonkey error reporter and store last SpiderMonkey error in // LastError property TSMEngine = class protected frt: PJSRuntime; fcx: PJSContext; fcomp: PJSCompartment; fNativeMethod: TSMEngineMethodEventDynArray; fNativeMethods: TDynArrayHashed; fNativeMethodCount: integer; FManager: TSMEngineManager; FGlobal: variant; FGlobalObject: TSMObject; FEngineContentVersion: Cardinal; FStringFinalizer: JSStringFinalizer; FThreadID: DWORD; FLastErrorMsg: RawUTF8; FLastErrorFileName: RawUTF8; FLastErrorLine: integer; FErrorExist: boolean; function InternalRegisterMethod(obj: PJSObject; const MethodName: SynUnicode; const Event: TMethod; Kind: TSMEngineMethodEventKind; ArgumentsCount: integer): PJSFunction; /// called from SpiderMonkey callback. Do not raise exception here // instead use CheckJSError metod after JSAPI compile/evaluate call procedure DoProcessJSError(errMsg: PCChar; report: PJSErrorReport); virtual; /// called from SpiderMonkey callback. It used for interrupt execution of script // when it executes too long function DoProcessOperationCallback: JSBool; virtual; procedure CancelExecution; protected // used by Watchdog thread state. See js.cpp fTimeOutAborted: Boolean; fTimedOut: Boolean; fWatchdogLock: PRLock; fWatchdogWakeup: PRCondVar; fWatchdogThread: PRThread; fWatchdogHasTimeout: Boolean; fWatchdogTimeout: Int64; fSleepWakeup: PRCondVar; fTimeoutInterval: double; function ScheduleWatchdog(t: Double): Boolean; procedure KillWatchdog; function InitWatchdog: boolean; procedure SetTimeoutValue(const Value: Double); public /// create one threadsafe JavaScript Engine instance // - initialize internal JSRuntime, JSContext, and global objects and // standard JavaScript classes // - do not create Engine directly via this constructor, but instead call // TSMEngineManager.ThreadSafeEngine constructor Create(aManager: TSMEngineManager); virtual; ................................................................................ // as in JavaScript: // ! var obj = {} procedure NewObject(out newobj: TSMObject); overload; /// create new JavaScript object with prototype // - JavaScript equivalent of // ! {}.__proto__ := prototype; procedure NewObject(const prototype: TSMObject; out newobj: TSMObject); overload; /// create new JavaScript object from its class procedure NewObjectWithClass(clasp: PJSClass; var newobj: TSMObject); overload; /// create new JavaScript object from its prototype procedure NewObjectWithClass(clasp: PJSClass; const prototype: TSMObject; const parent: TSMObject; var newobj: TSMObject); overload; /// create new JavaScript object from its class and property specifications procedure InitClass(clasp: PJSClass; ps: PJSPropertySpec; var newobj: TSMObject); /// converts a JavaScript value into a JavaScript object procedure MakeObject(const value: TSMValue; out obj: TSMObject); overload; {$ifdef HASINLINE}inline;{$endif} /// converts a JavaScript low-level value into a JavaScript object procedure MakeObject(const value: jsval; out obj: TSMObject); overload; /// converts a JavaScript low-level object into a JavaScript object procedure MakeObject(jsobj: PJSObject; out obj: TSMObject); overload; ................................................................................ property GlobalObject: TSMObject read FGlobalObject; /// access to the associated global object as low-level PJSObject property GlobalObj: PJSObject read FGlobalObject.fobj; /// access to the associated execution context property cx: PJSContext read fCx; /// access to the associated execution runtime property rt: PJSRuntime read frt; /// access to the associated execution compartment property comp: PJSCompartment read fcomp; /// internal version number of engine scripts // - used in TSMEngine.ThreadSafeEngine to determine if context is up to // date, in order to trigger on-the-fly reload of scripts without the need // if restarting the application // - caller must change this parameter value e.g. in case of changes in // the scripts folder in an HTTP server ................................................................................ property LastErrorMsg: RawUTF8 read FLastErrorMsg; /// last error source code line number triggered during JavaScript execution property LastErrorLine: integer read FLastErrorLine; /// last error file name triggered during JavaScript execution property LastErrorFileName: RawUTF8 read FLastErrorFileName; /// TRUE if an error was triggered during JavaScript execution property ErrorExist: boolean read FErrorExist; /// notifies a WatchDog timeout property TimeOutAborted: boolean read FTimeOutAborted; /// define a WatchDog timeout interval // - is set to -1 by default, i.e. meaning no execution timeout property TimeOutValue: Double read fTimeoutInterval write SetTimeoutValue; end; /// prototype of SpideMonkey notification callback method TEngineEvent = procedure(const Engine: TSMEngine) of object; /// main access point to the SpiderMonkey per-thread scripting engines ................................................................................ var /// define the TSynLog class used for logging for all our SynSM related units // - you may override it with TSQLLog, if available from mORMot.pas // - since not all exceptions are handled specificaly by this unit, you // may better use a common TSynLog class for the whole application or module SynSMLog: TSynLogClass=TSynLog; implementation uses Math; //DateUtils; const jsglobal_class: JSClass = (name: 'global'; flags: JSCLASS_HAS_PRIVATE or JSCLASS_GLOBAL_FLAGS { or JSCLASS_NEW_RESOLVE }; addProperty: JS_PropertyStub; delProperty: JS_DeletePropertyStub; getProperty: JS_PropertyStub; setProperty: JS_StrictPropertyStub; enumerate: @JS_EnumerateStub; resolve: JS_ResolveStub; convert: JS_ConvertStub //finalize is Optionally non-null member //in source it marked as Mandatory, but it doesn't //use in tests and there is no exported function JS_FinalizeStub ); /// handle errors from JavaScript. Just call DoProcessJSError of corresponding TSMEngine // to set TSMEngine error properties procedure ErrorReporter(cx: PJSContext; pErrMsg: PCChar; report: PJSErrorReport); cdecl; begin TSMEngine(cx.PrivateData).DoProcessJSError(pErrMsg, report) end; ................................................................................ if JS_IsExceptionPending(cx)=JS_FALSE then // raise only if this is the first exception in chain if aException is EOutOfMemory then JS_ReportOutOfMemory(cx) else JS_ReportError(cx, PCchar(AnsiString(aException.Message)+AnsiString(aContext))); end; function OperationCallback(cx: PJSContext): JSBool; cdecl; begin Result := TSMEngine(cx.PrivateData).DoProcessOperationCallback; end; { TSMEngine } // do nothing here procedure ExternalStringFinalizer(fin: PJSStringFinalizer; chars: Pjschar); cdecl; begin {} end; constructor TSMEngine.Create(aManager: TSMEngineManager); const Opt: CompartmentOptions = ( zoneSpec: zsFreshZone; hasVersion: True; version: JSVERSION_LATEST; ); begin if aManager = nil then raise ESMException.Create('No manager provided'); fNativeMethods.Init(TypeInfo(TSMEngineMethodEventDynArray), fNativeMethod,HashPointer,SortDynArrayPointer,nil,@fNativeMethodCount); TSynFPUException.ForLibraryCode; FManager := aManager; FEngineContentVersion := FManager.ContentVersion; frt := JS_NewRuntime(FManager.MaxPerEngineMemory, JS_USE_HELPER_THREADS); if frt = nil then raise ESMException.Create('Create runtime: out of memory'); fCx := JS_NewContext(rt, STACK_CHUNK_SIZE); if fCx = nil then raise ESMException.Create('JSContext create'); // You must set jsoBaseLine,jsoTypeInference,jsoIon for the enabling ION // ION is disabled without this options fCx.Options := [jsoVarObjFix,jsoBaseLine,jsoTypeInference,jsoIon,jsoAsmJs]; fStringFinalizer.finalize := ExternalStringFinalizer; JS_SetContextPrivate(cx, self); JS_SetErrorReporter(cx, ErrorReporter); FGlobalObject.fCx := cx; FGlobalObject.fObj := JS_NewGlobalObject(cx, @jsglobal_class, nil, @Opt); if GlobalObj = nil then raise ESMException.Create('Create global object'); fcomp := fcomp.EnterCompartment(cx,GlobalObj); if JS_InitStandardClasses(cx, GlobalObj)<>JS_TRUE then raise ESMException.Create('InitStandardClasses failure'); FGlobalObject.DefineProperty('global', GlobalObject.AsSMValue, [jspEnumerate,jspPermanent,jspReadOnly]); TSMVariantData(FGlobal).Init(FGlobalObject); fTimeoutInterval := -1; if not InitWatchdog then raise ESMException.Create('InitWatchDog failure'); JS_SetOperationCallback(cx, OperationCallback); end; destructor TSMEngine.Destroy; begin inherited Destroy; TSynFPUException.ForLibraryCode; //JS_RemoveExternalStringFinalizer(ExternalStringFinalizer); comp^.Destroy; if FThreadID=GetCurrentThreadId then cx^.Destroy; // SM 24 expects the context to be released in the same thread KillWatchdog; rt^.Destroy; end; procedure TSMEngine.DoProcessJSError(errMsg: PCChar; report: PJSErrorReport); const PATTERN: PUTF8Char = '[JSError %] % (%): %'; var exc: jsval; pExObj: PJSObject; FErrorStackTrace: RawUTF8; msg: SynUnicode; begin FErrorExist := True; if report^.filename = nil then FLastErrorFileName := '(w/o name)' else FLastErrorFileName := CurrentAnsiConvert.AnsiBufferToRawUTF8( report^.filename,StrLen(pointer(report^.filename))); FLastErrorLine := report^.lineno; if report^.ucmessage=nil then FLastErrorMsg := FormatUTF8(PATTERN,[report^.errorNumber,FLastErrorFileName, FLastErrorLine,errMsg]) else FLastErrorMsg := FormatUTF8(PATTERN,[report^.errorNumber,FLastErrorFileName, FLastErrorLine,PWideChar(report^.ucmessage)]); FErrorStackTrace := ''; if (JS_GetPendingException(cx, exc)=JS_TRUE) then begin if JSVAL_IS_OBJECT(exc) then begin pExObj := JSVAL_TO_OBJECT(exc); JS_GetProperty(cx, pExObj, 'stack', exc); if (exc <> JSVAL_VOID) and JSVAL_IS_STRING(exc) then begin msg := JSVAL_TO_STRING(exc).ToSynUnicode(cx); if msg <> '' then // this can happend in case syntax error while parse script FErrorStackTrace := SynUnicodeToUtf8(msg); end; end; end; end; procedure TSMEngine.CheckJSError(res: JSBool); begin if FTimeOutAborted then raise ESMException.Create('Script runs for too long, terminating.'); if FErrorExist then begin SynSMLog.Add.Log(sllError, FLastErrorMsg); raise ESMException.Create(UTF8ToString(FLastErrorMsg)); end; if res=JS_FALSE then begin SynSMLog.Add.Log(sllError, 'Error compiling script %', FLastErrorFileName); raise ESMException.CreateFmt('Error compiling script "%s". Line %d', ................................................................................ end; end; procedure TSMEngine.ClearLastError; begin JS_ClearPendingException(cx); FErrorExist := False; FTimeOutAborted := False; end; procedure TSMEngine.GarbageCollect; begin JS_GC(rt); end; procedure TSMEngine.MaybeGarbageCollect; begin JS_MaybeGC(cx); end; ................................................................................ procedure TSMEngine.NewObject(const prototype: TSMObject; out newobj: TSMObject); begin newobj.fCx := cx; newobj.fObj := JS_NewObject(cx, nil{class}, prototype.obj, nil{parent}); if newobj.fObj=nil then raise ESMException.Create('NewObject(prototype)'); end; procedure TSMEngine.NewObjectWithClass(clasp: PJSClass; var newobj: TSMObject); begin newobj.fCx := cx; newobj.fObj := JS_NewObject(cx, clasp, nil, nil); if newobj.fObj=nil then raise ESMException.Create('NewObject'); end; procedure TSMEngine.NewObjectWithClass(clasp: PJSClass; const prototype: TSMObject; const parent: TSMObject; var newobj: TSMObject); begin newobj.fCx := cx; newobj.fObj := JS_NewObject(cx, clasp, prototype.obj, parent.obj); if newobj.fObj=nil then raise ESMException.Create('NewObject'); end; procedure TSMEngine.InitClass(clasp: PJSClass; ps: PJSPropertySpec; var newobj: TSMObject); begin newobj.fCx := cx; newobj.fObj := JS_InitClass(cx, GlobalObj, nil, clasp, nil, 0, ps , nil, nil, nil); if newobj.obj=nil then raise ESMException.Create('NewObject'); end; procedure TSMEngine.MakeObject(const value: TSMValue; out obj: TSMObject); begin MakeObject(value.FValue,obj); end; procedure TSMEngine.MakeObject(const value: jsval; out obj: TSMObject); ................................................................................ JSVAL_TO_STRING(FValue).ToVariant(cx,result); JSTYPE_NUMBER: if JSVAL_IS_INT(FValue) then result := JSVAL_TO_INT(FValue) else result := JSVAL_TO_DOUBLE(FValue); JSTYPE_BOOLEAN: result := JSVAL_TO_BOOLEAN(FValue)=JS_TRUE; JSTYPE_FUNCTION: result := TransformToSynUnicode(cx); else raise ESMException.CreateFmt('Unhandled ToVariant(%d)',[ord(ValType(cx))]); end; end; procedure TSMValue.SetVariant(cx: PJSContext; const Value: Variant); ................................................................................ begin FValue := STRING_TO_JSVAL(cx^.NewJSString(aStr)); end; procedure TSMValue.SetNativeString(cx: PJSContext; const aStr: SynUnicode); begin FValue := STRING_TO_JSVAL(JS_NewExternalString(cx, pointer(aStr), length(aStr), @TSMEngine(cx.PrivateData).FStringFinalizer)); end; function TSMValue.ToDateTime(cx: PJSContext): TDateTime; var oDate: PJSObject; {$ifdef CONSIDER_TIME_IN_Z} // as defined in SynSM.inc ms: double; ms64: Int64; ................................................................................ ml := GetIntFuncPropVal('getMilliseconds'); Result := EncodeDateTime(Y, m, d, h, mn, s, ml); {$endif} end; procedure TSMValue.SetDateTime(cx: PJSContext; const Value: TDateTime); var dmsec: double; {$ifdef CONSIDER_TIME_IN_Z} // as defined in SynSM.inc oDate: PJSObject; {$else} // this realisation is buggy - it ignores timezone rules change history // for server-side realisation the best solution is to use GMT time here ms: Word; STLocal, STUtc: TSystemTime; TZ: TTimeZoneInformation; AUTCDateTime: TDateTime; {$endif} begin {$ifdef CONSIDER_TIME_IN_Z} dmsec := DateTimeToUnixMSTime(Value); oDate := JS_NewDateObjectMsec(cx, dmsec); if JS_ObjectIsDate(cx, oDate)<>JS_TRUE then raise ESMException.CreateFmt('SetDateTime(%g): not a valid date',[Value]); FValue := oDate.ToJSValue; {$else} DateTimeToSystemTime(Value, STLocal); GetTimeZoneInformation(TZ); // use TzSpecificLocalTimeToSystemTime? TZ.Bias := -TZ.Bias; TZ.StandardBias := -TZ.StandardBias; TZ.DaylightBias := -TZ.DaylightBias; ................................................................................ inc(buf); end; RawUnicodeToUtf8(name,buf-name,result); end; function writeCallback(const buf: Pjschar; len: uint32; data: pointer): JSBool; cdecl; begin TTextWriter(data).AddNoJSONEscapeW(pointer(buf),len); result := JS_TRUE; end; procedure TSMValue.AddJSON(cx: PJSContext; W: TTextWriter); begin if @self=nil then W.AddShort('null') else ................................................................................ JSTYPE_NUMBER: if JSVAL_IS_INT(FValue) then W.Add(JSVAL_TO_INT(FValue)) else W.Add(JSVAL_TO_DOUBLE(FValue)); JSTYPE_BOOLEAN: W.AddString(JSON_BOOLEAN[JSVAL_TO_BOOLEAN(FValue)=JS_TRUE]); JSTYPE_OBJECT, JSTYPE_FUNCTION: JS_Stringify(cx, @FValue, nil, JSVAL_NULL, writeCallback, pointer(W)); else raise ESMException.CreateFmt('Unhandled AddJSON(%d)',[ord(ValType(cx))]); end; end; function TSMValue.ToJSON(cx: PJSContext): RawUTF8; ................................................................................ lineNo: Cardinal; out result: TSMValue); var r: JSBool; eng: TSMEngine; begin TSynFPUException.ForLibraryCode; eng := Engine; eng.ClearLastError; eng.ScheduleWatchdog(eng.fTimeoutInterval); r := JS_EvaluateUCScript(cx, obj, pointer(script), length(script), pointer(scriptName), lineNo, Result.FValue); eng.ScheduleWatchdog(-1); eng.CheckJSError(r); end; procedure TSMObject.RunMethod(const methodName: CString; const argv: SMValArray; out rval: TSMValue); var r: JSBool; eng: TSMEngine; begin TSynFPUException.ForLibraryCode; eng := Engine; eng.ScheduleWatchdog(Engine.fTimeoutInterval); r := JS_CallFunctionName(cx, obj, pointer(methodName), Length(argv), pointer(argv), rval.FValue); eng.ScheduleWatchdog(-1); eng.CheckJSError(r); end; procedure TSMObject.RunMethod(const methodName: CString; const argv: array of const; out rval: TSMValue); var args: SMValArray; a: integer; begin ................................................................................ procedure TSMObject.UnRoot; begin if obj<>nil then JS_RemoveObjectRoot(cx, @obj); end; function TSMObject.DefineNativeMethod(const methodName: SynUnicode; func: JSNative; nargs: uintN; attrs: TJSPropertyAttrs=[jspEnumerate]): PJSFunction; begin Result := JS_DefineUCFunction(cx, obj, Pjschar(methodName), Length(methodName), func, nargs, word(attrs)); if Result=nil then raise ESMException.CreateFmt('Impossible to define native method "%s"',[methodName]); end; function TSMObject.DefineNativeMethod(const methodName: AnsiString; func: JSNative; nargs: uintN; attrs: TJSPropertyAttrs=[jspEnumerate]): PJSFunction; begin Result := JS_DefineFunction(cx, obj, PCChar(methodName), func, nargs, word(attrs)); if Result=nil then raise ESMException.CreateFmt('Impossible to define native method "%s"',[methodName]); end; function TSMObject.Parent: TSMObject; begin result.fCx := cx; if obj=nil then result.fObj := nil else result.fObj := JS_GetParent(obj); end; function TSMObject.Prototype: TSMObject; begin result.fCx := cx; if obj=nil then result.fObj := nil else JS_GetPrototype(cx, obj, result.fObj); end; function TSMEngine.DoProcessOperationCallback: JSBool; begin if fTimedOut then Result := JS_FALSE else Result := JS_TRUE; end; procedure TSMEngine.CancelExecution; begin fTimedOut := True; FTimeOutAborted := True; FErrorExist := True; FLastErrorFileName := '(w/o name)'; FLastErrorLine := 0; FLastErrorMsg := FormatUTF8('JSError. Filename: %. Line %. Message: %', [FLastErrorFileName, FLastErrorLine, 'Script runs for too long, terminating']); JS_TriggerOperationCallback(rt); end; function TSMEngine.InitWatchdog: boolean; begin Assert(not Assigned(fWatchdogThread)); fWatchdogLock := PR_NewLock; if Assigned(fWatchdogLock) then begin fWatchdogWakeup := PR_NewCondVar(fWatchdogLock); if Assigned(fWatchdogWakeup) then begin fSleepWakeup := PR_NewCondVar(fWatchdogLock); if Assigned(fSleepWakeup) then begin result := True; exit; end; PR_DestroyCondVar(fWatchdogWakeup); end; end; result := False; end; procedure TSMEngine.KillWatchdog; var thread: PRThread; begin PR_Lock(fWatchdogLock); thread := fWatchdogThread; if Assigned(thread) then begin // The watchdog thread is running, tell it to terminate waking it up // if necessary. fWatchdogThread := nil; PR_NotifyCondVar(fWatchdogWakeup); end; PR_Unlock(fWatchdogLock); if Assigned(thread) then PR_JoinThread(thread); PR_DestroyCondVar(fSleepWakeup); PR_DestroyCondVar(fWatchdogWakeup); PR_DestroyLock(fWatchdogLock); end; function IsBefore( t1, t2: int64): Boolean; begin Result := int32(t1 - t2) < 0; end; procedure WatchdogMain(arg: pointer); cdecl; var eng: TSMEngine; rt: PJSRuntime; now_: int64; sleepDuration: uint64; status: PRStatus; begin PR_SetCurrentThreadName('JS Watchdog'); eng := TSMEngine(arg); rt := eng.rt; PR_Lock(eng.fWatchdogLock); while Assigned(eng.fWatchdogThread) do begin now_ := JS_Now(); if (eng.fWatchdogHasTimeout and not IsBefore(now_, eng.fWatchdogTimeout)) then begin // The timeout has just expired. Trigger the operation callback outside the lock eng.fWatchdogHasTimeout := false; PR_Unlock(eng.fWatchdogLock); eng.CancelExecution; PR_Lock(eng.fWatchdogLock); // Wake up any threads doing sleep PR_NotifyAllCondVar(eng.fSleepWakeup); end else begin if (eng.fWatchdogHasTimeout) then begin // Time hasn't expired yet. Simulate an operation callback // which doesn't abort execution. JS_TriggerOperationCallback(rt); end; sleepDuration := PR_INTERVAL_NO_TIMEOUT; if (eng.fWatchdogHasTimeout) then sleepDuration := PR_TicksPerSecond() div 10; status := PR_WaitCondVar(eng.fWatchdogWakeup, sleepDuration); Assert(status = PR_SUCCESS); end end; PR_Unlock(eng.fWatchdogLock); end; function TSMEngine.ScheduleWatchdog(t: Double): Boolean; var interval: Int64; timeout: Int64; begin if (t <= 0) then begin PR_Lock(fWatchdogLock); fWatchdogHasTimeout := false; PR_Unlock(fWatchdogLock); result := true; exit; end; interval := int64(ceil(t * PRMJ_USEC_PER_SEC)); timeout := JS_Now() + interval; PR_Lock(fWatchdogLock); if not Assigned(fWatchdogThread) then begin Assert(not fWatchdogHasTimeout); fWatchdogThread := PR_CreateThread(PR_USER_THREAD, @WatchdogMain, Self, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if not Assigned(fWatchdogThread) then begin PR_Unlock(fWatchdogLock); Result := false; Exit; end end else if (not fWatchdogHasTimeout or IsBefore(timeout, fWatchdogTimeout)) then begin PR_NotifyCondVar(fWatchdogWakeup); end; fWatchdogHasTimeout := true; fWatchdogTimeout := timeout; PR_Unlock(fWatchdogLock); Result := true; end; procedure TSMEngine.SetTimeoutValue(const Value: Double); begin fTimeoutInterval := Value; ScheduleWatchdog(Value); end; function TSMObject.GetPrivate: pointer; {$ifdef WITHASSERT} var C: PJSClass; {$endif} begin if obj=nil then result := nil else {$ifdef WITHASSERT} // JS_GetPrivate can return some not-nil pointer when we call JS_GetPrivate for object // with class which has no flag JSCLASS_HAS_PRIVATE begin C := JS_GetClass(obj); if C.flags and JSCLASS_HAS_PRIVATE = 0 then result := nil // May be need to raise exception else {$endif} result := JS_GetPrivate(obj); {$ifdef WITHASSERT} end; {$endif} end; procedure TSMObject.SetPrivate(const Value: pointer); {$ifdef WITHASSERT} var C: PJSClass; {$endif} begin if obj<>nil then {$ifdef WITHASSERT} begin // If we set private data into object with class which has no flag JSCLASS_HAS_PRIVATE // SM don't raise exception, but we can get AV in any other place C := JS_GetClass(obj); if C.flags and JSCLASS_HAS_PRIVATE = 0 then exit // May be need to raise exception else {$endif} JS_SetPrivate(obj, Value); {$ifdef WITHASSERT} end; {$endif} end; function TSMObject.GetPrivateData(expectedClass: PJSClass): pointer; begin if obj=nil then result := nil else result := JS_GetInstancePrivate(cx, obj, expectedClass, nil); ................................................................................ VObject.fCx := aCx; VObject.fObj := aObj; end; initialization Assert(sizeof(TSMVariantData)=sizeof(variant)); end. |
Changes to SynSMAPI.pas.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 .. 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 .. 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 ... 170 171 172 173 174 175 176 177 178 179 180 181 182 183 ... 208 209 210 211 212 213 214 215 216 217 218 219 220 221 ... 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 ... 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 ... 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 ... 345 346 347 348 349 350 351 352 353 354 355 356 357 358 ... 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 ... 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 ... 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 ... 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 ... 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 ... 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 ... 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 ... 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 ... 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 .... 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 .... 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 .... 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 .... 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 .... 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 .... 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 .... 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 .... 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 .... 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 .... 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 .... 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 .... 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 .... 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 .... 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 .... 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 .... 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 |
The Initial Developer of the Original Code is Pavel Mashlyakovsky. Portions created by the Initial Developer are Copyright (C) 2014 the Initial Developer. All Rights Reserved. Contributor(s): - Arnaud Bouchez Alternatively, the contents of this file may be used under the terms of either the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to ................................................................................ ***** END LICENSE BLOCK ***** --------------------------------------------------------------------------- Download the SpiderMonkey library at http://synopse.info/files/synsm.7z ! --------------------------------------------------------------------------- Version 1.18 - initial release. Use SpiderMonkey 1.8.5 https://developer.mozilla.org/en-US/docs/SpiderMonkey/1.8.5 - add JSString.ToJSVal method - change JS_ARGV macro result type to PjsvalVector road map: write Tjsval - object (record) wraper for jsval with methods Is* To* As* migrate to IonMonkey compile mozjs without nspr enable ctypes? for byte array work #ifdef JS_HAS_CTYPES JS_InitCTypesClass ................................................................................ SynCommons; const {$ifdef MSWINDOWS} {$ifdef CPU64} SpiderMonkeyLib = 'mozjs64.dll'; {$else} SpiderMonkeyLib = 'mozjs.dll'; {$endif} {$endif} {$ifdef LINUX} // for Kylix SpiderMonkeyLib = 'mozjs.so'; {$endif} ................................................................................ // so let's do it for future now // - in all cases see JSFloat64 - NSPR's floating point type is always 64 bits. jsdouble = Double; /// Pointer to JSScript structure defined if jsscript.h // - we do not directly use of this structure, so we define just a pointer PJSScript = type Pointer; // **************************************************************************** // * jstypes.h conversion * // * basic types * // **************************************************************************** type /// type appropriate for most signed integer variables for SMAPI ................................................................................ /// type for pointer arithmetic difference // - Variables of this type are suitable for storing a pointer or pointer sutraction ptrdiff_t = PtrInt; /// type for pointer arithmetic difference for SMAPI // - Variables of this type are suitable for storing a pointer or pointer sutraction JSPtrdiff = ptrdiff_t; /// boolean type for variables and parameter types for SMAPI // - Use JS_FALSE and JS_TRUE constants for clarity of target type in assignments JSBool = JSIntn; /// pointer to boolean type for variables and parameter types for SMAPI PJSBool = ^JSBool; ................................................................................ // **************************************************************************** // * jsbuiltins.h conversion * // * "object" types * // **************************************************************************** /// available options for JS Objects TJSOption = ( jsoStrict, jsoWError, jsoVarObjFix, jsoPrivateIsNSISupports, jsoCompileNGo, jsoAtLine, jsoXML, jsoUnused1, jsoDontReportUncaught, jsoRelimit, jsoAnonFunFix, jsoObsoleteJIT, jsoNoScriptRVal, jsoUnrootedGlobal, jsoMethodJIT, jsoObsoleteProfiling, jsoMethodAlwaysJIT); /// set of available options for JS Objects TJSOptions = set of TJSOption; /// available options for JS Objects Properties TJSPropertyAttr = ( jspEnumerate, jspReadOnly, jspPermanent, jspUnused, jspGetter, jspSetter, jspShared, jspIndex, sjpShortID); ................................................................................ // - this object does not store anything, but just provide some helper methods // to access a PPJSContext value via JS_*Context*(..) API functions JSContext = object private function GetOptions: TJSOptions; procedure SetOptions(const Value: TJSOptions); function GetVersion: JSVersion; procedure SetVersion(const Value: JSVersion); function GetPrivate: Pointer; {$ifdef HASINLINE}inline;{$endif} procedure SetPrivate(const Value: Pointer); protected public /// wrapper to JS_DestroyContext(@self) procedure Destroy; ................................................................................ /// wrapper to JS_GetRuntime(@self) function Runtime: PJSRuntime; /// wrapper to JS_InitStandardClasses(@self,global) function InitStandardClasses(global: PJSObject): boolean; /// wrapper to JS_GetOptions()/JS_SetOptions() property Options: TJSOptions read GetOptions write SetOptions; /// wrapper to JS_GetVersion()/JS_SetVersion() property Version: JSVersion read GetVersion write SetVersion; /// wrapper to JS_GetVersion() and string conversion function VersionToString: RawUTF8; /// wrapper to JS_GetContextPrivate()/JS_SetContextPrivate() property PrivateData: Pointer read GetPrivate write SetPrivate; public /// create a new JavaScript string instance from a given UTF-8 text function NewJSString(const Value: RawUTF8): PJSString; overload; ................................................................................ /// wrapper to JS_UnLockRuntime(@self) procedure Unlock; /// wrapper to JS_DestroyRuntime(@self) procedure Destroy; /// wrapper to JS_GetRuntimePrivate()/JS_SetRuntimePrivate() property PrivateData: Pointer read GetPrivate write SetPrivate; end; /// JavaScript string instance // - this object does not store anything, but just provide some helper methods // to access a PPJSString value via JS_*String*(..) API functions // - use function JSContext.NewJSString() to create a new instance for a given // execution context // - to understand string in SpiderMonkey good point is comments in vm\String.h ................................................................................ JSTYPE_VOID, { undefined } JSTYPE_OBJECT, { object } JSTYPE_FUNCTION, { function } JSTYPE_STRING, { string } JSTYPE_NUMBER, { number } JSTYPE_BOOLEAN, { boolean } JSTYPE_NULL, { null } JSTYPE_XML, { xml object } JSTYPE_LIMIT ); /// js_CheckAccess mode enumeration JSAccessMode = ( JSACC_PROTO = 0, { XXXbe redundant w.r.t. id } JSACC_PARENT = 1, { XXXbe redundant w.r.t. id } { * enum value #2 formerly called JSACC_IMPORT, * gap preserved for ABI compatibility. } JSACC_WATCH = 3, { a watchpoint on object foo for id 'bar' } JSACC_READ = 4, { a "get" of foo.bar } JSACC_WRITE = 8, { a "set" of foo.bar = baz } ................................................................................ JSENUMERATE_NEXT, //* Destroy iterator state. */ JSENUMERATE_DESTROY ); // JSClass (and js::ObjectOps where appropriate) function pointer typedefs. /// JSClass method prototype to add, delete, or get a property named by id in obj // - note the jsid id type -- id may be a string (Unicode property identifier) // or an int (element index) // - the vp out parameter, on success, is the new property value after // an add or get. After a successful delete, *vp is JSVAL_FALSE iff // obj[id] can't be deleted (because it's permanent) JSPropertyOp = function(cx: PJSContext; obj: PJSObject; id: jsid; vp: pjsval):JSBool; cdecl; /// JSClass method prototype to set a property named by id in obj, treating // the assignment as strict mode code if strict is true // - note the jsid id type -- id may be a string (Unicode property identifier) // or an int (element index) // - the vp out parameter, on success, is the new property value after the set JSStrictPropertyOp = function(cx: PJSContext; obj: PJSObject; id: jsid; strict: JSBool; vp: pjsval): JSBool; cdecl; /// function prototype used for callbacks that enumerate the properties of // a JSObject // - The behavior depends on the value of enum_op // -The return value is used to indicate success, with a value of JS_FALSE // indicating failure. JSNewEnumerateOp = function(cx: PJSContext; obj: PJSObject; enum_op: JSIterateOp; statep: pjsval; idp: pjsid): JSBool; cdecl; /// The old-style JSClass.enumerate op should define all lazy properties not // yet reflected in obj. JSEnumerateOp = function(cx: PJSContext; obj: PJSObject): JSBool; cdecl; /// function prototype used to resolve a lazy property named by id in obj // by defining it directly in obj // - Lazy properties are those reflected from some peer native property space // (e.g., the DOM attributes for a given node reflected as obj) on demand. // - JS looks for a property in an object, and if not found, tries to resolve // the given id. If resolve succeeds, the engine looks again in case resolve // defined obj[id]. If no such property exists directly in obj, the process // is repeated with obj's prototype, etc. // - NB: JSNewResolveOp provides a cheaper way to resolve lazy properties. JSResolveOp = function(cx: PJSContext; obj: PJSObject; id: jsid): JSBool; cdecl; /// function prototype used to resolve a lazy property named by id in obj // by defining it directly in obj // - Like JSResolveOp, but flags provide contextual information as follows: // ! JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id // ! JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment // ! JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence ................................................................................ // in a prototype object whose class led to the resolve hook being called. // - When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore // null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no // JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry. // This is not good practice, but enough existing hook implementations count // on it that we can't break compatibility by passing the starting object in // *objp without a new JSClass flag. JSNewResolveOp = function(cx: PJSContext; obj: PJSObject; id: jsid; flags: uintN; var objp: PPJSObject): JSBool; cdecl; // Convert obj to the given type, returning true with the resulting value in // vp on success, and returning false on error or exception. JSConvertOp = function(cx: PJSContext; obj: PJSObject; typ: JSType; vp: pjsval): JSBool; cdecl; /// callback used to delegate typeof to an object so it can cloak a // primitive or another object JSTypeOfOp = function(cx: PJSContext; obj: PJSObject): JSType; cdecl; /// Finalize obj, which the garbage collector has determined to be unreachable // from other live objects or from GC roots. Obviously, finalizers must never // store a reference to obj. JSFinalizeOp = procedure(cx: PJSContext; obj: PJSObject); cdecl; /// callback used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer // to extend and reduce the set of string types finalized by the GC. JSStringFinalizeOp = procedure(cx: PJSContext; obj: PJSString); cdecl; /// JSClass.checkAccess type: check whether obj[id] may be accessed per mode, // returning false on error/exception, true on success with obj[id]'s last-got // value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id // is either a string or an int jsval. JSCheckAccessOp = function(cx: PJSContext; obj: PJSObject; id: jsid; mode: JSAccessMode; vp: Pjsval): JSBool; cdecl; /// state value as expected by JSXDRObjectOp() prototype PJSXDRState = type Pointer; /// Encode or decode an object, given an XDR state record representing external data JSXDRObjectOp = function(xdr: PJSXDRState; var objp: PJSObject): JSBool; cdecl; ................................................................................ // - cx is the execution context // - argc is the number of supplied arguments // - vp[0] is the callee - see JS_CALLEE() // - vp[1] is the object instance - see JS_THIS() // - vp[2]..vp[argc+1] are the supplied arguments - see JS_ARGV_PTR() JSNative = function(cx: PJSContext; argc: uintN; vp: Pjsval): JSBool; cdecl; /// callback typedef for marking functions called by the JS VM JSMarkOp = function(cx: PJSContext; obj: PJSObject; arg: Pointer): uint32; cdecl; /// flag used for JSContextCallback() argument // - JSCONTEXT_NEW: JS_NewContext successfully created a new JSContext // instance. The callback can initialize the instance as // required. If the callback returns false, the instance // will be destroyed and JS_NewContext returns null. In // this case the callback is not called again. ................................................................................ // - the possible values for contextOp when the runtime calls the callback // are defined by JSContextOp JSContextCallback = function(cx: PJSContext; contextOp: uintN): JSBool; cdecl; /// flag used for callback for a given runtime context garbage collection JSGCStatus = ( JSGC_BEGIN, JSGC_END, JSGC_MARK_END, JSGC_FINALIZE_END ); /// callback prototype for a given runtime context garbage collection JSGCCallback = function(cx: PJSContext; status: JSGCStatus): JSBool; cdecl; /// generic operaiton callback prototype for a given runtime context JSOperationCallback = function(cx: PJSContext): JSBool; cdecl; /// internal structure used to report JavaScript errors JSErrorReport = record /// source file name, URL, etc., or null filename: PCChar; /// source line number lineno: uintN; /// offending source line without final #13 linebuf: PCChar; /// pointer to error token in linebuf tokenptr: PCChar; /// unicode (original) line buffer uclinebuf: Pjschar; /// unicode (original) token pointer uctokenptr: Pjschar; /// error/warning, etc. flags: uintN; /// the error number, e.g. see js.msg errorNumber: uintN; /// the (default) error message ucmessage: Pjschar; /// arguments for the error message messageArgs: PPjschar; end; /// map an internal structure used to report JavaScript errors PJSErrorReport = ^JSErrorReport; /// callback prototype for reporting error for a given runtime context JSErrorReporter = procedure(cx: PJSContext; _message: PCChar; report: PJSErrorReport); cdecl; /// Possible exception types ................................................................................ JSVAL_TYPE_INT32 = Byte($01); JSVAL_TYPE_UNDEFINED= Byte($02); JSVAL_TYPE_BOOLEAN = Byte($03); JSVAL_TYPE_MAGIC = Byte($04); JSVAL_TYPE_STRING = Byte($05); JSVAL_TYPE_NULL = Byte($06); JSVAL_TYPE_OBJECT = Byte($07); JSVAL_TYPE_NONFUNOBJ= Byte($57); JSVAL_TYPE_FUNOBJ = Byte($67); JSVAL_TYPE_STRORNULL= Byte($97); JSVAL_TYPE_OBJORNULL= Byte($98); JSVAL_TYPE_BOXED = Byte($99); JSVAL_TYPE_UNINITIALIZED= Byte($cd); //JSValueTag {$IFDEF CPU32} type JSValueTag = Cardinal; const JSVAL_TAG_CLEAR = Cardinal($FFFF0000); JSVAL_TAG_INT32 = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_INT32); JSVAL_TAG_UNDEFINED= Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_UNDEFINED); JSVAL_TAG_STRING = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_STRING); JSVAL_TAG_BOOLEAN = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_BOOLEAN); JSVAL_TAG_MAGIC = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_MAGIC); JSVAL_TAG_NULL = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_NULL); JSVAL_TAG_OBJECT = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_OBJECT); {$ELSE} //CPU64 type JSValueTag = Cardinal; const JSVAL_TAG_MAX_DOUBLE= Cardinal($0001FFF0); JSVAL_TAG_INT32 = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_INT32); JSVAL_TAG_UNDEFINED = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_UNDEFINED); ................................................................................ JSVAL_SHIFTED_TAG_OBJECT = QWord(JSVAL_TAG_OBJECT) shl JSVAL_TAG_SHIFT; {$ENDIF} JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET = JSVAL_TYPE_NULL; JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET = JSVAL_TYPE_OBJECT; JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET = JSVAL_TYPE_INT32; JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET = JSVAL_TYPE_MAGIC; JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET = JSVAL_TYPE_OBJECT; JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET = JSVAL_TYPE_FUNOBJ; {$ifdef CPU32} //#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type))) JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET = JSVAL_TAG_NULL; JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET = JSVAL_TAG_OBJECT; JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET = JSVAL_TAG_INT32; JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET = JSVAL_TAG_STRING; {$else} // CPU64 JSVAL_PAYLOAD_MASK : QWord = $00007FFFFFFFFFFF; JSVAL_TAG_MASK : QWord = $FFFF800000000000; //#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type))) //#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT) JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET = JSVAL_SHIFTED_TAG_NULL; JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET = JSVAL_SHIFTED_TAG_OBJECT; JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET = JSVAL_SHIFTED_TAG_UNDEFINED; JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET = JSVAL_SHIFTED_TAG_MAGIC; JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET = JSVAL_SHIFTED_TAG_STRING; {$endif} type JSWhyMagic = ( JS_ARRAY_HOLE, // a hole in a dense array JS_ARGS_HOLE, // a hole in the args object's array */ JS_NATIVE_ENUMERATE, // indicates that a custom enumerate hook forwarded // to js_Enumerate, which really means the object can be // enumerated like a native object. */ JS_NO_ITER_VALUE, // there is not a pending iterator value */ JS_GENERATOR_CLOSING, // exception value thrown when closing a generator */ JS_NO_CONSTANT, // compiler sentinel value */ JS_THIS_POISON, // used in debug builds to catch tracing errors */ JS_ARG_POISON, // used in debug builds to catch tracing errors */ JS_SERIALIZE_NO_NODE, // an empty subnode in the AST serializer */ JS_GENERIC_MAGIC // for local use */ ); // here must be jsval_layout struct defenition and *_IMPL functions // but it moved to implementation part of unit, because used only internaly ................................................................................ JSVAL_NULL : QWord = QWord((QWord(JSVAL_TAG_NULL) shl CPU_SHIFT) or 0); JSVAL_ZERO : QWord = QWord((QWord(JSVAL_TAG_INT32) shl CPU_SHIFT) or 0); JSVAL_ONE : QWord = QWord((QWord(JSVAL_TAG_INT32) shl CPU_SHIFT) or 1); JSVAL_FALSE : QWord = QWord((QWord(JSVAL_TAG_BOOLEAN) shl CPU_SHIFT) or JS_FALSE); JSVAL_TRUE : QWord = QWord((QWord(JSVAL_TAG_BOOLEAN) shl CPU_SHIFT) or JS_TRUE); JSVAL_VOID : QWord = QWord((QWord(JSVAL_TAG_UNDEFINED) shl CPU_SHIFT) or 0); JSRUNMODE_INTERP = 0; JSRUNMODE_TRACEJIT = 1; JSRUNMODE_METHODJIT = 2; JSRUNMODE_COUNT = 3; type jsint = JSInt32; jsuint = JSUInt32; //#define JSVAL_BITS(v) ((v).asBits) //#define JSVAL_FROM_LAYOUT(l) (l) //#define IMPL_TO_JSVAL(v) (v) ................................................................................ // A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or // JS_IdToValue must be used instead. const JSID_TYPE_STRING = $0; JSID_TYPE_INT = $1; JSID_TYPE_VOID = $2; JSID_TYPE_OBJECT = $4; JSID_TYPE_DEFAULT_XML_NAMESPACE = $6; JSID_TYPE_MASK = $7; //TODO make jsid macro conversion jsapi.h line 308-462 //#define JSVAL_LOCK(cx,v) (JSVAL_IS_GCTHING(v) \ // ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v)) \ // : JS_TRUE) //#define JSVAL_UNLOCK(cx,v) (JSVAL_IS_GCTHING(v) \ ................................................................................ property; don't copy the property on set of the same-named property in an object that delegates to a prototype containing this property } JSPROP_INDEX = $80; { name is actually (jsint) index } JSPROP_SHORTID = $100; { set in JSPropertyDescriptor.attrs if getters/setters use a shortid } { Function flags, set in JSFunctionSpec and passed to JS_NewFunction etc. } JSFUN_LAMBDA = $08; { expressed, not declared, function } JSFUN_HEAVYWEIGHT = $80; { activation requires a Call object } { = $0100 is unused } JSFUN_CONSTRUCTOR = $0200; { native that can be called as a ctor without creating a this object } JSFUN_FLAGS_MASK = $07f8; { overlay JSFUN_* attributes -- bits 12-15 are used internally to flag interpreted functions } JSFUN_STUB_GSOPS = $1000; { use JS_PropertyStub getter/setter instead of defaulting to class gsops for property holding function } {* Re-use JSFUN_LAMBDA, which applies only to scripted functions, for use in * JSFunctionSpec arrays that specify generic native prototype methods, i.e., * methods of a class prototype that are exposed as static methods taking an * extra leading argument: the generic |this| parameter. * * If you set this flag in a JSFunctionSpec struct's flags initializer, then * that struct must live at least as long as the native static method object * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically * JSFunctionSpec structs are allocated in static arrays. } JSFUN_GENERIC_NATIVE = JSFUN_LAMBDA; function JS_Now: int64; cdecl; external SpiderMonkeyLib; function JS_GetNaNValue(cx: PJSContext): jsval; cdecl; external SpiderMonkeyLib; function JS_GetNegativeInfinityValue(cx: PJSContext): jsval; cdecl; external SpiderMonkeyLib; function JS_GetPositiveInfinityValue(cx: PJSContext): jsval; cdecl; external SpiderMonkeyLib; function JS_GetEmptyStringValue(cx: PJSContext): jsval; cdecl; external SpiderMonkeyLib; function JS_GetEmptyString(cx: PJSRuntime): PJSString; cdecl; external SpiderMonkeyLib; ................................................................................ // - SameValue slightly differs from strict equality (===) in that +0 and -0 are // not the same and in that NaN is the same as NaN function JS_SameValue(cx: PJSContext; v1, v2: jsval; equal: PJSBool): JSBool; cdecl; external SpiderMonkeyLib; //***************************************************************************** //* Initialization, locking, contexts, and memory allocation. //***************************************************************************** // * It is important that the first runtime and first context be created in a // * single-threaded fashion, otherwise the behavior of the library is undefined. // * See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference // */ // some aliases defined in SM: // #define JS_NewRuntime JS_Init // #define JS_DestroyRuntime JS_Finish // #define JS_LockRuntime JS_Lock // #define JS_UnlockRuntime JS_Unlock /// Initialize the JavaScript runtime // - JS_NewRuntime initializes the JavaScript runtime environment. // Call JS_NewRuntime before making any other API calls. // - JS_NewRuntime allocates memory for the JSRuntime and initializes certain // internal runtime structures. maxbytes specifies the number of allocated // bytes after which garbage collection is run. function JS_NewRuntime(maxbytes: uint32): PJSRuntime; cdecl; external SpiderMonkeyLib name 'JS_Init'; /// Release the JavaScript runtime procedure JS_DestroyRuntime(rt: PJSRuntime); cdecl; external SpiderMonkeyLib name 'JS_Finish'; /// Free all resources used by the JS engine, not associated with specific runtimes procedure JS_ShutDown; function JS_GetRuntimePrivate(rt: PJSRuntime): pointer; cdecl; external SpiderMonkeyLib; procedure JS_SetRuntimePrivate(rt: PJSRuntime; data: pointer); cdecl; external SpiderMonkeyLib; ................................................................................ function JS_ContextIterator(rt: PJSRuntime; iterp: PPJSContext): PJSContext; cdecl; external SpiderMonkeyLib; /// retrieve the JavaScript version number used within a specified executable script context function JS_GetVersion(cx: PJSContext): JSVersion; cdecl; external SpiderMonkeyLib; /// configure a JSContext to use a specific version of the JavaScript language function JS_SetVersion(cx: PJSContext; version: JSVersion): JSVersion; cdecl; external SpiderMonkeyLib; /// retrieve the JavaScript version text used within a specified executable script context function JS_VersionToString(version: JSVersion): PCChar; cdecl; external SpiderMonkeyLib; /// configure a JSContext to use a specific version of the JavaScript language function JS_StringToVersion(_string: PCChar): JSVersion; cdecl; external SpiderMonkeyLib; const JSOPTION_STRICT = 1 shl 0; { warn on dubious practice } JSOPTION_WERROR = 1 shl 1; { convert warning to error } JSOPTION_VAROBJFIX = 1 shl 2; { make JS_EvaluateScript use the last object on its 'obj' params scope chain as the ECMA 'variables object' } JSOPTION_PRIVATE_IS_NSISUPPORTS = 1 shl 3; { context private data points to an nsISupports subclass } JSOPTION_COMPILE_N_GO = 1 shl 4; { caller of JS_Compile*Script promises to execute compiled script once only; enables compile-time scope chain resolution of consts. } JSOPTION_ATLINE = 1 shl 5; { //@line number ["filename"] option supported for the XUL preprocessor and kindred beasts. } JSOPTION_XML = 1 shl 6; { EMCAScript for XML support: parse <!-- --> as a token, not backward compatible with the comment-hiding hack used in HTML script tags. } JSOPTION_DONT_REPORT_UNCAUGHT = 1 shl 8; { When returning from the outermost API call, prevent uncaught exceptions from being converted to error reports } JSOPTION_RELIMIT = 1 shl 9; { Throw exception on any regular expression which backtracks more than n^3 times, where n is length of the input string } JSOPTION_ANONFUNFIX = 1 shl 10; { Disallow function () in statement context per ECMA-262 Edition 3. } {$IFNDEF JS_188} //Obsolete since JSAPI 11 JSOPTION_JIT = 1 shl 11; { Enable JIT compilation. } {$ENDIF} JSOPTION_NO_SCRIPT_RVAL = 1 shl 12; { A promise to the compiler that a null rval out-param will be passed to each call to JS_ExecuteScript. } JSOPTION_UNROOTED_GLOBAL = 1 shl 13; { The GC will not root the contexts' global objects (see JS_GetGlobalObject), leaving that up to the embedding. } JSOPTION_METHODJIT = 1 shl 14; { Whole-method JIT. } {$IFNDEF JS_188} //Obsolete JSOPTION_PROFILING = 1 shl 15; { Profiler to make tracer/methodjit choices. } {$ENDIF} JSOPTION_METHODJIT_ALWAYS= 1 shl 16; { Always whole-method JIT, don't tune at run-time. } { Options which reflect compile-time properties of scripts. } JSCOMPILEOPTION_MASK = (JSOPTION_XML or JSOPTION_ANONFUNFIX); JSRUNOPTION_MASK = (1 shl 17 and not JSCOMPILEOPTION_MASK); JSALLOPTION_MASK = (JSCOMPILEOPTION_MASK or JSRUNOPTION_MASK); function JS_GetOptions(cx: PJSContext): uint32; cdecl; external SpiderMonkeyLib; function JS_SetOptions(cx: PJSContext; options: uint32): uint32; cdecl; external SpiderMonkeyLib; function JS_ToggleOptions(cx: PJSContext; options: uint32): uint32; cdecl; external SpiderMonkeyLib; function JS_GetImplementationVersion: PCChar; cdecl; external SpiderMonkeyLib ; // here is some *Compartment* functions - Compartment is obsolete, so we do not import them ................................................................................ cdecl; external SpiderMonkeyLib; procedure JS_free(cx: PJSContext; p: Pointer); cdecl; external SpiderMonkeyLib; procedure JS_updateMallocCounter(cx: PJSContext; nbytes: size_t); cdecl; external SpiderMonkeyLib; function JS_strdup(cx: PJSContext; s: PCChar): PCChar; cdecl; external SpiderMonkeyLib; /// tips: JS_NewNumberValue(cx, 0) is NOT JSVAL_IS_DOUBLE!! function JS_NewNumberValue(cx: PJSContext; d: double; var rval: jsval): JSBool; cdecl; external SpiderMonkeyLib; /// The JS_Add*Root functions add a C/C++ variable to the garbage collector's root set, // the set of variables used as starting points each time the collector checks // to see what memory is reachable // - The garbage collector aggressively collects // and recycles memory that it deems unreachable, so roots are often necessary // to protect data from being prematurely collected. ................................................................................ cdecl; external SpiderMonkeyLib; function JS_AddGCThingRoot(cx: PJSContext; rp: PPointer): JSBool; cdecl; external SpiderMonkeyLib; function JS_RemoveGCThingRoot(cx: PJSContext; rp: PPointer): JSBool; cdecl; external SpiderMonkeyLib; // here miss trace functions procedure JS_GC(cx: PJSContext); cdecl; external SpiderMonkeyLib; procedure JS_MaybeGC(cx: PJSContext); cdecl; external SpiderMonkeyLib; function JS_SetGCCallback(cx: PJSContext; cb: JSGCCallback): JSGCCallback; cdecl; external SpiderMonkeyLib; function JS_SetGCCallbackRT(rt: PJSRuntime; cb: JSGCCallback): JSGCCallback; cdecl; external SpiderMonkeyLib; function JS_IsAboutToBeFinalized(cx: PJSContext; thing: Pointer): JSBool; cdecl; external SpiderMonkeyLib; type JSGCParamKey = ( // Maximum nominal heap before last ditch GC. JSGC_MAX_BYTES = 0, // Number of JS_malloc bytes before last ditch GC. JSGC_MAX_MALLOC_BYTES = 1, // Obsolete since JSAPI 12 JSGC_STACKPOOL_LIFESPAN = 2, // Obsolete since JSAPI 6 JSGC_TRIGGER_FACTOR = 3, //* Amount of bytes allocated by the GC. */ JSGC_BYTES = 4, //* Number of times when GC was invoked. */ JSGC_NUMBER = 5, //* Max size of the code cache in bytes. */ JSGC_MAX_CODE_CACHE_BYTES = 6, //* Select GC mode. */ JSGC_MODE = 7, //* Number of GC chunks waiting to expire. */ JSGC_UNUSED_CHUNKS = 8 ); JSGCMode = ( //* Perform only global GCs. */ JSGC_MODE_GLOBAL = 0, //* Perform per-compartment GCs until too much garbage has accumulated. */ JSGC_MODE_COMPARTMENT = 1 ); procedure JS_SetGCParameter(rt: PJSRuntime; key: JSGCParamKey; value: uint32); cdecl; external SpiderMonkeyLib; function JS_GetGCParameter(rt: PJSRuntime; key: JSGCParamKey): uint32; cdecl; external SpiderMonkeyLib; ................................................................................ cdecl; external SpiderMonkeyLib; /// Flush the code cache for the current thread // - The operation might be delayed if the cache cannot be flushed currently // because native code is currently executing. procedure JS_FlushCaches(cx: PJSContext); cdecl; external SpiderMonkeyLib; /// Add a finalizer for external strings created by JS_NewExternalString (see // below) using a type-code returned from this function, and that understands // how to free or release the memory pointed at by JS_GetStringChars(str) // - Return a nonnegative type index if there is room for finalizer in the // global GC finalizers table, else return -1. If the engine is compiled // JS_THREADSAFE and used in a multi-threaded environment, this function must // be invoked on the primordial thread only, at startup -- or else the entire // program must single-thread itself while loading a module that calls this // function. function JS_AddExternalStringFinalizer(finalizer: JSStringFinalizeOp): intN; cdecl; external SpiderMonkeyLib; /// Creates a new JSString whose characters are stored in external memory, i.e., // memory allocated by the application, not the JavaScript engine // - Since the program allocated the memory, it will need to free it; // this happens in an external string finalizer indicated by the type parameter. // - chars is Pointer to the first element of an array of jschars. // This array is used as the character buffer of the JSString to be created. // The array must be populated with the desired character data before JS_NewExternalString // is called, and the array must remain in memory, with its contents unchanged, // for as long as the JavaScript engine needs to hold on to it. // (Ultimately, the string will be garbage collected, and the JavaScript engine will // call the string finalizer callback, allowing the application to free the array) // - The text buffer array does not need to be zero-terminated. function JS_NewExternalString(cx: PJSContext; chars: pjschar; length: size_t; _type: intN): PJSString; cdecl; external SpiderMonkeyLib; /// Remove finalizer from the global GC finalizers table, returning its type // code if found, -1 if not found. // - As with JS_AddExternalStringFinalizer, there is a threading restriction // if you compile the engine JS_THREADSAFE: this function may be called for a // given finalizer pointer on only one thread; different threads may call to // remove distinct finalizers safely. // - You must ensure that all strings with finalizer's type have been collected // before calling this function. Otherwise, string data will be leaked by the // GC, for want of a finalizer to call. function JS_RemoveExternalStringFinalizer(finalizer: JSStringFinalizeOp): intN; cdecl; external SpiderMonkeyLib; /// Returns the external-string finalizer index for this string, or -1 if it is // an "internal" (native to JS engine) string. //TODO - in current compiled version there is no this functions. seems like a BUG!!!!!!!! //JS_GetExternalStringGCType //function JS_IsExternalString(rt: PJSRuntime; str: PJSString): intN; cdecl; external SpiderMonkeyLib; ................................................................................ JSClassInternal = procedure; cdecl; PJSClass = ^JSClass; JSClass = record name: PCChar; flags: uint32; //* Mandatory non-null function pointer members. */ addProperty: JSPropertyOp; delProperty: JSPropertyOp; getProperty: JSPropertyOp; setProperty: JSStrictPropertyOp; enumerate: JSEnumerateOp; resolve: JSResolveOp; convert: JSConvertOp; finalize: JSFinalizeOp; //* Optionally non-null members start here. */ reserved0: JSClassInternal; checkAccess: JSCheckAccessOp; call: JSNative; construct: JSNative; xdrObject: JSXDRObjectOp; hasInstance: JSHasInstanceOp; mark: JSMarkOp; reserved1: JSClassInternal; {$IFDEF JS_188} reserved: array [0..39] of pointer; {$ELSE} reserved: array [0..18] of pointer; {$ENDIF} end; const /// JSClass instance objects have private slot JSCLASS_HAS_PRIVATE = 1 shl 0; /// JSClass instance has JSNewEnumerateOp hook JSCLASS_NEW_ENUMERATE = 1 shl 1; /// JSClass instance has JSNewResolveOp hook JSCLASS_NEW_RESOLVE = 1 shl 2; /// JSClass instance private is (nsISupports JSCLASS_PRIVATE_IS_NSISUPPORTS = 1 shl 3; {$IFDEF JS_188} /// JSClass instance JSNewResolveOp gets starting object in prototype chain // passed in via *objp in/out parameter JSCLASS_NEW_RESOLVE_GETS_START = 1 shl 4; /// JSClass instanceDOM document observer JSCLASS_DOCUMENT_OBSERVER = 1 shl 6; {$ELSE} /// JSClass instance JSNewResolveOp gets starting object in prototype chain // passed in via *objp in/out parameter JSCLASS_NEW_RESOLVE_GETS_START = 1 shl 5; /// JSClass instance call constructor on class prototype JSCLASS_CONSTRUCT_PROTOTYPE = 1 shl 6; /// JSClass instance DOM document observer JSCLASS_DOCUMENT_OBSERVER = 1 shl 7; {$ENDIF} /// JSClass instance room for 8 flags below JSCLASS_RESERVED_SLOTS_SHIFT = 8; /// JSClass instance and 16 above this field JSCLASS_RESERVED_SLOTS_WIDTH = 8; JSCLASS_RESERVED_SLOTS_MASK = (JSUint32(1) shl JSCLASS_RESERVED_SLOTS_WIDTH)-1; JSCLASS_HIGH_FLAGS_SHIFT = (JSCLASS_RESERVED_SLOTS_SHIFT + JSCLASS_RESERVED_SLOTS_WIDTH); JSCLASS_IS_GLOBAL = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+2)); JSRESERVED_GLOBAL_SLOTS_COUNT = 6; /// JSProto_LIMIT is length of #include "jsproto.tbl" JSProto_LIMIT = 39; JSRESERVED_GLOBAL_THIS = (JSProto_LIMIT * 3); JSRESERVED_GLOBAL_THROWTYPEERROR = (JSRESERVED_GLOBAL_THIS + 1); JSRESERVED_GLOBAL_REGEXP_STATICS = (JSRESERVED_GLOBAL_THROWTYPEERROR + 1); JSRESERVED_GLOBAL_FUNCTION_NS = (JSRESERVED_GLOBAL_REGEXP_STATICS + 1); JSRESERVED_GLOBAL_EVAL_ALLOWED = (JSRESERVED_GLOBAL_FUNCTION_NS + 1); JSRESERVED_GLOBAL_FLAGS = (JSRESERVED_GLOBAL_EVAL_ALLOWED + 1); JSCLASS_GLOBAL_FLAGS = JSCLASS_IS_GLOBAL or (((JSRESERVED_GLOBAL_THIS + JSRESERVED_GLOBAL_SLOTS_COUNT) and JSCLASS_RESERVED_SLOTS_MASK) shl JSCLASS_RESERVED_SLOTS_SHIFT); procedure JS_DestroyIdArray(cx: PJSContext; ida: PJSIdArray); cdecl; external SpiderMonkeyLib; function JS_ValueToId(cx: PJSContext; v: jsval; var id: jsid): JSBool; cdecl; external SpiderMonkeyLib; function JS_IdToValue(cx: PJSContext; id: jsid; var v: jsval): JSBool; cdecl; external SpiderMonkeyLib; ................................................................................ JSRESOLVE_DECLARING = $08; /// used by JS_ResolveStub() callback: class name used when constructing JSRESOLVE_CLASSNAME = $10; /// used by JS_ResolveStub() callback: resolve inside a with statement JSRESOLVE_WITH = $20; /// default callback matching JSPropertyOp prototype of JSClass function JS_PropertyStub(cx: PJSContext; obj: PJSObject; id: jsid; vp: pjsval): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSStrictPropertyOp prototype of JSClass function JS_StrictPropertyStub(cx: PJSContext; obj: PJSObject; id: jsid; _strict: JSBool; vp: pjsval): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSEnumerateOp prototype of JSClass function JS_EnumerateStub(cx: PJSContext; obj: PJSObject): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSResolveOp prototype of JSClass function JS_ResolveStub(cx: PJSContext; obj: PJSObject; id: jsid): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSConvertOp prototype of JSClass function JS_ConvertStub(cx: PJSContext; obj: PJSObject; _type: JSType; vp: pjsval): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSFinalizeOp prototype of JSClass procedure JS_FinalizeStub(cx: PJSContext; obj: PJSObject); cdecl; external SpiderMonkeyLib; type /// JS object constant definition JSConstDoubleSpec = record dval: jsdouble; name: PCChar; flags: uint8; spare: array[0..2] of uint8; end; PJSConstDoubleSpec = ^JSConstDoubleSpec; TJSConstDoubleSpecArray = array of JSConstDoubleSpec; /// JS object property defenition JSPropertySpec = record name: PCChar; tinyid: int8; flags: uint8; getter: JSPropertyOp; setter: JSStrictPropertyOp; end; PJSPropertySpec = ^JSPropertySpec; TJSPropertySpecArray = array of JSPropertySpec; /// Defines a single function for an object. JSFunctionSpec = record name: PCChar; call: JSNative; nargs: uint16; flags: uint16; end; PJSFunctionSpec = ^JSFunctionSpec; TJSFunctionSpecArray = array of JSFunctionSpec; /// Make a JSClass accessible to JavaScript code by creating its prototype, // constructor, properties, and functions // - see https://developer.mozilla.org/en-US/docs/SpiderMonkey/JSAPI_Reference/JS_InitClass function JS_InitClass(cx: PJSContext; obj: PJSObject; parent_proto: PJSObject; clasp: PJSClass; _constructor: JSNative; nargs: uintN; ps: PJSPropertySpec; fs: PJSFunctionSpec; static_ps: PJSPropertySpec; static_fs: PJSFunctionSpec): PJSObject; cdecl; external SpiderMonkeyLib ; /// retrieve the JSClass of a given object {$ifdef JS_THREADSAFE} function JS_GetClass(cx: PJSContext; obj: PJSObject): PJSClass; cdecl; external SpiderMonkeyLib name 'JS_GetClass'; {$else} function _JS_GetClass(obj: PJSObject): PJSClass; cdecl; external SpiderMonkeyLib name 'JS_GetClass'; function JS_GetClass(cx: PJSContext; obj: PJSObject): PJSClass; {$ifdef HASINLINE}inline;{$endif} {$endif} function JS_InstanceOf(cx: PJSContext; obj: PJSObject; clasp: PJSClass; argv: pjsval): JSBool; cdecl; external SpiderMonkeyLib; function JS_HasInstance(cx: PJSContext; obj: PJSObject; v: jsval; bp: PJSBool): JSBool; cdecl; external SpiderMonkeyLib; function JS_GetPrivate(cx: PJSContext; obj: PJSObject): Pointer; cdecl; external SpiderMonkeyLib; function JS_SetPrivate(cx: PJSContext; obj: PJSObject; data: Pointer): JSBool; cdecl; external SpiderMonkeyLib; function JS_GetInstancePrivate(cx: PJSContext; obj: PJSObject; clasp: PJSClass; argv: pjsval): Pointer; cdecl; external SpiderMonkeyLib; function JS_GetPrototype(cx: PJSContext; obj: PJSObject): PJSObject; cdecl; external SpiderMonkeyLib; function JS_SetPrototype(cx: PJSContext; obj: PJSObject; proto: PJSObject): JSBool; cdecl; external SpiderMonkeyLib; function JS_GetParent(cx: PJSContext; obj: PJSObject): PJSObject; cdecl; external SpiderMonkeyLib; function JS_SetParent(cx: PJSContext; obj: PJSObject; parent: PJSObject): JSBool; cdecl; external SpiderMonkeyLib; function JS_GetConstructor(cx: PJSContext; proto: PJSObject): PJSObject; cdecl; external SpiderMonkeyLib; /// Get a unique identifier for obj, good for the lifetime of obj (even if it // is moved by a copying GC) // - Return false on failure (likely out of memory), and true with idp // containing the unique id on success function JS_GetObjectId(cx: PJSContext; obj: PJSObject; idp: Pjsid): JSBool; cdecl; external SpiderMonkeyLib; /// JS_NewGlobalObject creates a new global object based on the specified class // - The new object has no parent. It initially has no prototype either, // since it is typically the first object created; // call JS_InitStandardClasses to create all the standard objects, // including Object.prototype, and set the global object's prototype function JS_NewGlobalObject(cx: PJSContext; clasp: PJSClass): PJSObject; cdecl; external SpiderMonkeyLib; {$ifndef JS_188} type PJSPrincipals = Pointer; /// JS_NewCompartmentAndGlobalObject has been removed in bug 755186. Use JS_NewGlobalObject instead. function JS_NewCompartmentAndGlobalObject(cx: PJSContext; clasp: PJSClass; principals: PJSPrincipals): PJSObject; cdecl; external SpiderMonkeyLib; {$endif} /// JS_NewObject creates a new object based on a specified class, prototype, // and parent object // - cx is a pointer to a context associated with the runtime // in which to establish the new object. // - clasp is a pointer to an existing class to use for internal methods, such as finalize // - proto is an optional pointer to the prototype object with which to associate the new object ................................................................................ id: jsid; flags: uintN; var objp: PJSObject; var vp: jsval): JSBool; cdecl; external SpiderMonkeyLib; type JSPropertyDescriptor = record obj: PJSObject; attrs: uintN; getter: JSPropertyOp; setter: JSStrictPropertyOp; value: jsval; shortid: uintN; end; PJSPropertyDescriptor = ^JSPropertyDescriptor; /// Finds a specified property of an object and gets a detailed description of that property function JS_GetPropertyDescriptorById(cx: PJSContext; obj: PJSObject; id: jsid; flags: uintN; objp: PPJSObject; desc: PJSPropertyDescriptor): JSBool; cdecl; external SpiderMonkeyLib; ................................................................................ cdecl; external SpiderMonkeyLib ; /// Unicode version to compiles a script function JS_CompileUCScript(cx: PJSContext; obj: PJSObject; chars: Pjschar; length: size_t; filename: PCChar; lineno: uintN): PJSScript; cdecl; external SpiderMonkeyLib ; /// JS_CompileUTF8File compiles the text of script in an external file location // for execution by the JS engine // - filename is the name of the file containing the script to compile. // - On success, JS_CompileUTF8File returns an object that represents // the newly compiled script. Otherwise it returns NULL. // - To compile JavaScript code that is already in memory, use JS_CompileScript instead // - To compile code from a stdio FILE, use JS_CompileFileHandle // - Warning! File MUST be without BOM function JS_CompileUTF8File(cx: PJSContext; obj: PJSObject; filename: PCChar): PJSScript; cdecl; external SpiderMonkeyLib name 'JS_CompileFile'; /// Compile a script, reading the source code from a stdio FILE // - On success, JS_CompileUTF8FileHandle reads file to EOF and returns an // object representing the newly compiled script. // - If an error occurs during compilation, JS_CompileUTF8FileHandle stops // reading from the file and returns NULL. function JS_CompileUTF8FileHandle(cx: PJSContext; obj: PJSObject; filename: PCChar; fh: THandle): PJSScript; cdecl; external SpiderMonkeyLib name 'JS_CompileFileHandle'; type TCStringVector = array[0..0] of PCChar; PCStringVector = ^TCStringVector; /// JS_CompileFunction compiles a function from a text string, bytes, and // optionally associates it with a JS object, obj ................................................................................ /// retrieve the callback function that is automatically called periodically while // JavaScript code runs in the given execution context function JS_GetOperationCallback(cx: PJSContext): JSOperationCallback; cdecl; external SpiderMonkeyLib; /// triggers a callback set using JS_SetOperationCallback procedure JS_TriggerOperationCallback(cx: PJSContext); cdecl; external SpiderMonkeyLib; /// determines if a script or function is currently executing in a specified // JSContext, cx // - If a script is executing, JS_IsRunning returns JS_TRUE // - Otherwise it returns JS_FALSE. function JS_IsRunning(cx: PJSContext): JSBool; cdecl; external SpiderMonkeyLib; ................................................................................ 1: (u32: uint32); 2: (boo: JSBool); 3: (str: PJSString); 4: (obj: PJSObject); 5: (ptr: pointer); 6: (why: JSWhyMagic); 7: (word: jsuword); end; {$ifdef IS_LITTLE_ENDIAN} jsval_val_layout = packed record payload: jsval_payload; tag: JSValueTag; end; {$else} //BIG_ENDIAN ................................................................................ case Byte of 0: (asBits: QWord); 1: (s: jsval_val_layout); 2: (asDouble: double); 3: (asPtr: Pointer); end; implementation // **************************************************************************** // * jsval.h *_IMPL functions * // **************************************************************************** ................................................................................ if JSVAL_IS_OBJECT_IMPL(l) then Result := uint32(JS_FALSE) else Result := uint32(JS_TRUE); end; {$endif} //CPU64 // **************************************************************************** // * jsapi.h functions * // **************************************************************************** function JSVAL_IS_NULL(const v: jsval): Boolean; begin ................................................................................ end; procedure JSContext.SetPrivate(const Value: Pointer); begin JS_SetContextPrivate(@self,Value); end; procedure JSContext.SetVersion(const Value: JSVersion); begin JS_SetVersion(@self,Value) end; function JSContext.NewJSString(const Value: RawUTF8): PJSString; begin result := NewJSString(pointer(Value),length(Value),CP_UTF8); end; function JSContext.NewJSString(const Value: SynUnicode): PJSString; begin ................................................................................ function JSObject.ToJSValue: jsval; begin if @self=nil then result := JSVAL_NULL else result := OBJECT_TO_JSVAL(@self); end; // procedure JS_ShutDown; cdecl; external SpiderMonkeyLib; procedure JS_ShutDown; // avoid need of mozjs.dll even if not used var Shutdown: procedure; cdecl; begin Shutdown := GetProcAddress(GetModuleHandle(SpiderMonkeyLib),'JS_ShutDown'); if Assigned(Shutdown) then Shutdown; end; initialization assert(1 shl ord(jsoMethodAlwaysJIT)=JSOPTION_METHODJIT_ALWAYS); assert(1 shl ord(sjpShortID)=JSPROP_SHORTID); finalization JS_ShutDown; end. |
> | | > > | | > | > > > > > > > > > > > > | | | | | | > > > > > > > > > > > > > > > > > > | < > > > > | | > > > > > > > > > | | | | > | | > | | | | | | > > > > > > > > > > > > > | < < > > > > > | > > > > < < < < < < | | | | | | | | > < < < < < | < | | | | | | | | | > > > > > > > > > | < < < < < < < < < < < < < < < < < | | | < < > > | | | | > > | | | | | | < > > > > > > > | | | | | < < | | | | < < < < < < | | | | | < < < < < < < < > > > | < < < < | | | | | | | | | | < > > | < < < > > > > > | < < > | < < > | | < < < > | | | < | > | > > > > | > > | | > > > > > > > > > > > > > > | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | > > > > | < | < > | | | | < < < | | < < < < < < < < < < < < | | | | | | < | > | > > > | | < < | > | < < | < < < | | < | > | | | | | | | < < < < < < | | | < > | > | | | < | < < < < < | | < | | | | | | | | | | | > > > > > > > > > > > > > > > > | | > > > > > > | | | > | | | < < < | | < < < < | | | | | > > > > > > > > > > > > > > > > | | | | | | > | < | > | < > < < < < < < < < < < < < < < < < < < < < < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < > > > > > > > > > > > > > > > > | | |
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 .. 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 .. 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 ... 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 ... 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 ... 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 ... 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 ... 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 ... 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 ... 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 ... 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 ... 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 ... 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 ... 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 ... 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 ... 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 ... 971 972 973 974 975 976 977 978 979 980 981 982 983 984 .... 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 .... 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 .... 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 .... 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 .... 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 .... 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 .... 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 .... 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 .... 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 .... 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 .... 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 .... 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 .... 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 .... 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 .... 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 .... 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 .... 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 |
The Initial Developer of the Original Code is Pavel Mashlyakovsky. Portions created by the Initial Developer are Copyright (C) 2014 the Initial Developer. All Rights Reserved. Contributor(s): - Arnaud Bouchez - Vadim Orel Alternatively, the contents of this file may be used under the terms of either the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to ................................................................................ ***** END LICENSE BLOCK ***** --------------------------------------------------------------------------- Download the SpiderMonkey library at http://synopse.info/files/synsm.7z ! --------------------------------------------------------------------------- Version 1.18 - initial release. Use SpiderMonkey 24 https://developer.mozilla.org/en-US/docs/SpiderMonkey/24 and Modify jsapi.h for possibility import from Delphi and jsapi.cpp for possibility use JS_NumberValue - add JSString.ToJSVal method - change JS_ARGV macro result type to PjsvalVector - add debugger support functions road map: write Tjsval - object (record) wraper for jsval with methods Is* To* As* migrate to IonMonkey compile mozjs without nspr enable ctypes? for byte array work #ifdef JS_HAS_CTYPES JS_InitCTypesClass ................................................................................ SynCommons; const {$ifdef MSWINDOWS} {$ifdef CPU64} SpiderMonkeyLib = 'mozjs64.dll'; {$else} SpiderMonkeyLib = 'mozjs-24.dll'; NSPRLib = 'libnspr4.dll'; {$endif} {$endif} {$ifdef LINUX} // for Kylix SpiderMonkeyLib = 'mozjs.so'; {$endif} ................................................................................ // so let's do it for future now // - in all cases see JSFloat64 - NSPR's floating point type is always 64 bits. jsdouble = Double; /// Pointer to JSScript structure defined if jsscript.h // - we do not directly use of this structure, so we define just a pointer PJSScript = type Pointer; // **************************************************************************** // * jstypes.h conversion * // * basic types * // **************************************************************************** type /// type appropriate for most signed integer variables for SMAPI ................................................................................ /// type for pointer arithmetic difference // - Variables of this type are suitable for storing a pointer or pointer sutraction ptrdiff_t = PtrInt; /// type for pointer arithmetic difference for SMAPI // - Variables of this type are suitable for storing a pointer or pointer sutraction JSPtrdiff = ptrdiff_t; /// ordinal type used for pointer arithmetic // - Variables of this type are suitable for storing a pointer or pointer sutraction JSUIntPtr = PtrUInt; /// pointer on an ordinal type used for pointer arithmetic PJSuintptr = ^JSuintptr; /// ordinal type used for pointer arithmetic // - Variables of this type are suitable for storing a pointer or pointer sutraction JSUptrdiff = JSUintPtr ; /// boolean type for variables and parameter types for SMAPI // - Use JS_FALSE and JS_TRUE constants for clarity of target type in assignments JSBool = JSIntn; /// pointer to boolean type for variables and parameter types for SMAPI PJSBool = ^JSBool; ................................................................................ // **************************************************************************** // * jsbuiltins.h conversion * // * "object" types * // **************************************************************************** /// available options for JS Objects TJSOption = ( jsoExtraWarning, jsoWError, jsoVarObjFix, jsoPrivateIsNSISupports, jsoCompileNGo, jsoUnused5, jsoUnused6, jsoUnused7, jsoDontReportUncaught, jsoUnused9, jsoUnused10, jsoUnused11, jsoNoScriptRVal, jsoUnrootedGlobal, jsoBaseLine, jsoPcCount, jsoTypeInference, jsoStrictMode, jsoIon, jsoAsmJS); /// set of available options for JS Objects TJSOptions = set of TJSOption; /// available options for JS Objects Properties TJSPropertyAttr = ( jspEnumerate, jspReadOnly, jspPermanent, jspUnused, jspGetter, jspSetter, jspShared, jspIndex, sjpShortID); ................................................................................ // - this object does not store anything, but just provide some helper methods // to access a PPJSContext value via JS_*Context*(..) API functions JSContext = object private function GetOptions: TJSOptions; procedure SetOptions(const Value: TJSOptions); function GetVersion: JSVersion; // JS_SetVersion is not supported now Use CompartmentOptions in JS_NewGlobalObject function GetPrivate: Pointer; {$ifdef HASINLINE}inline;{$endif} procedure SetPrivate(const Value: Pointer); protected public /// wrapper to JS_DestroyContext(@self) procedure Destroy; ................................................................................ /// wrapper to JS_GetRuntime(@self) function Runtime: PJSRuntime; /// wrapper to JS_InitStandardClasses(@self,global) function InitStandardClasses(global: PJSObject): boolean; /// wrapper to JS_GetOptions()/JS_SetOptions() property Options: TJSOptions read GetOptions write SetOptions; /// wrapper to JS_GetVersion()/JS_SetVersion() property Version: JSVersion read GetVersion; /// wrapper to JS_GetVersion() and string conversion function VersionToString: RawUTF8; /// wrapper to JS_GetContextPrivate()/JS_SetContextPrivate() property PrivateData: Pointer read GetPrivate write SetPrivate; public /// create a new JavaScript string instance from a given UTF-8 text function NewJSString(const Value: RawUTF8): PJSString; overload; ................................................................................ /// wrapper to JS_UnLockRuntime(@self) procedure Unlock; /// wrapper to JS_DestroyRuntime(@self) procedure Destroy; /// wrapper to JS_GetRuntimePrivate()/JS_SetRuntimePrivate() property PrivateData: Pointer read GetPrivate write SetPrivate; end; /// points to a JavaScript execution compartment // - allows convenient access of JSCompartment wrapper methods PJSCompartment = ^JSCompartment; /// JavaScript execution compartment // - this object does not store anything, but just provide some helper methods // to access a PJSRuntime value via JS_*Runtime*(..) API functions JSCompartment = object private fcx: PJSContext; public /// initialize and enter a JavaScript execution compartment function EnterCompartment(cx: PJSContext; target: PJSObject): PJSCompartment; /// leave a JavaScript execution compartment procedure Destroy; end; /// JavaScript string instance // - this object does not store anything, but just provide some helper methods // to access a PPJSString value via JS_*String*(..) API functions // - use function JSContext.NewJSString() to create a new instance for a given // execution context // - to understand string in SpiderMonkey good point is comments in vm\String.h ................................................................................ JSTYPE_VOID, { undefined } JSTYPE_OBJECT, { object } JSTYPE_FUNCTION, { function } JSTYPE_STRING, { string } JSTYPE_NUMBER, { number } JSTYPE_BOOLEAN, { boolean } JSTYPE_NULL, { null } // JSTYPE_XML is not supported now JSTYPE_LIMIT ); /// js_CheckAccess mode enumeration JSAccessMode = ( JSACC_PROTO = 0, { XXXbe redundant w.r.t. id } { * enum value #1 formerly called JSACC_PARENT, * gap preserved for ABI compatibility. } { * enum value #2 formerly called JSACC_IMPORT, * gap preserved for ABI compatibility. } JSACC_WATCH = 3, { a watchpoint on object foo for id 'bar' } JSACC_READ = 4, { a "get" of foo.bar } JSACC_WRITE = 8, { a "set" of foo.bar = baz } ................................................................................ JSENUMERATE_NEXT, //* Destroy iterator state. */ JSENUMERATE_DESTROY ); // JSClass (and js::ObjectOps where appropriate) function pointer typedefs. /// JSClass method prototype to add, or get a property named by id in obj // - note the jsid id type -- id may be a string (Unicode property identifier) // or an int (element index) // - the vp out parameter, on success, is the new property value after // an add or get. After a successful delete, *vp is JSVAL_FALSE iff // obj[id] can't be deleted (because it's permanent) JSPropertyOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid; vp: pjsval): JSBool; cdecl; /// JSClass method prototype to delete a property named by id in obj // - note the jsid id type -- id may be a string (Unicode property identifier) // or an int (element index) // - the *succeeded out parameter, on success, is the JSVAL_TRUE. *succeeded is // JSVAL_FALSE if obj[id] can't be deleted (because it's permanent) JSDeletePropertyOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid; succeeded: PJSBool):JSBool; cdecl; /// JSClass method prototype to set a property named by id in obj, treating // the assignment as strict mode code if strict is true // - note the jsid id type -- id may be a string (Unicode property identifier) // or an int (element index) // - the vp out parameter, on success, is the new property value after the set JSStrictPropertyOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid; strict: JSBool; vp: pjsval): JSBool; cdecl; /// function prototype used for callbacks that enumerate the properties of // a JSObject // - The behavior depends on the value of enum_op // -The return value is used to indicate success, with a value of JS_FALSE // indicating failure. JSNewEnumerateOp = function(cx: PJSContext; var obj: PJSObject; enum_op: JSIterateOp; statep: pjsval; idp: pjsid): JSBool; cdecl; /// The old-style JSClass.enumerate op should define all lazy properties not // yet reflected in obj. JSEnumerateOp = function(cx: PJSContext; var obj: PJSObject): JSBool; cdecl; /// function prototype used to resolve a lazy property named by id in obj // by defining it directly in obj // - Lazy properties are those reflected from some peer native property space // (e.g., the DOM attributes for a given node reflected as obj) on demand. // - JS looks for a property in an object, and if not found, tries to resolve // the given id. If resolve succeeds, the engine looks again in case resolve // defined obj[id]. If no such property exists directly in obj, the process // is repeated with obj's prototype, etc. // - NB: JSNewResolveOp provides a cheaper way to resolve lazy properties. JSResolveOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid): JSBool; cdecl; /// function prototype used to resolve a lazy property named by id in obj // by defining it directly in obj // - Like JSResolveOp, but flags provide contextual information as follows: // ! JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id // ! JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment // ! JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence ................................................................................ // in a prototype object whose class led to the resolve hook being called. // - When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore // null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no // JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry. // This is not good practice, but enough existing hook implementations count // on it that we can't break compatibility by passing the starting object in // *objp without a new JSClass flag. JSNewResolveOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid; flags: uintN; var objp: PPJSObject): JSBool; cdecl; // Convert obj to the given type, returning true with the resulting value in // vp on success, and returning false on error or exception. JSConvertOp = function(cx: PJSContext; var obj: PJSObject; typ: JSType; vp: pjsval): JSBool; cdecl; /// callback used to delegate typeof to an object so it can cloak a // primitive or another object JSTypeOfOp = function(cx: PJSContext; var obj: PJSObject): JSType; cdecl; /// Finalize obj, which the garbage collector has determined to be unreachable // from other live objects or from GC roots. Obviously, finalizers must never // store a reference to obj. JSFinalizeOp = procedure(cx: PJSContext; var obj: PJSObject); cdecl; /// callback used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer // to extend and reduce the set of string types finalized by the GC. JSStringFinalizeOp = procedure(cx: PJSContext; var obj: PJSString); cdecl; /// JSClass.checkAccess type: check whether obj[id] may be accessed per mode, // returning false on error/exception, true on success with obj[id]'s last-got // value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id // is either a string or an int jsval. JSCheckAccessOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid; mode: JSAccessMode; vp: Pjsval): JSBool; cdecl; /// state value as expected by JSXDRObjectOp() prototype PJSXDRState = type Pointer; /// Encode or decode an object, given an XDR state record representing external data JSXDRObjectOp = function(xdr: PJSXDRState; var objp: PJSObject): JSBool; cdecl; ................................................................................ // - cx is the execution context // - argc is the number of supplied arguments // - vp[0] is the callee - see JS_CALLEE() // - vp[1] is the object instance - see JS_THIS() // - vp[2]..vp[argc+1] are the supplied arguments - see JS_ARGV_PTR() JSNative = function(cx: PJSContext; argc: uintN; vp: Pjsval): JSBool; cdecl; /// callback used for trace operation of a given class // - enumerate all traceable things reachable from obj's private data structure. // - For each such thing, a trace implementation must call one of the // JS_Call*Tracer variants on the thing. // - JSTraceOp implementation can assume that no other threads mutates object // state. It must not change state of the object or corresponding native // structures. The only exception for this rule is the case when the embedding // needs a tight integration with GC. In that case the embedding can check if // the traversal is a part of the marking phase through calling // JS_IsGCMarkingTracer and apply a special code like emptying caches or // marking its native structures. JSTraceOp = procedure(cx: PJSContext; argc: uintN; vp: Pjsval); cdecl; /// a JavaScript tracer instance PJSTracer = Pointer; /// flag used for JSContextCallback() argument // - JSCONTEXT_NEW: JS_NewContext successfully created a new JSContext // instance. The callback can initialize the instance as // required. If the callback returns false, the instance // will be destroyed and JS_NewContext returns null. In // this case the callback is not called again. ................................................................................ // - the possible values for contextOp when the runtime calls the callback // are defined by JSContextOp JSContextCallback = function(cx: PJSContext; contextOp: uintN): JSBool; cdecl; /// flag used for callback for a given runtime context garbage collection JSGCStatus = ( JSGC_BEGIN, JSGC_END ); /// callback prototype for a given runtime context garbage collection JSGCCallback = function(cx: PJSContext; status: JSGCStatus): JSBool; cdecl; /// generic operaiton callback prototype for a given runtime context JSOperationCallback = function(cx: PJSContext): JSBool; cdecl; /// Security protocol PJSPrincipals = Pointer; /// internal structure used to report JavaScript errors JSErrorReport = record /// source file name, URL, etc., or null filename: PCChar; /// see 'originPrincipals' comment above originPrincipals: PJSPrincipals; /// source line number lineno: uintN; /// offending source line without final #13 linebuf: PCChar; /// pointer to error token in linebuf tokenptr: PCChar; /// unicode (original) line buffer uclinebuf: Pjschar; /// unicode (original) token pointer uctokenptr: Pjschar; /// error/warning, etc. flags: uintN; /// the error number, e.g. see js.msg errorNumber: uintN; /// the (default) error message ucmessage: Pjschar; /// arguments for the error message messageArgs: PPjschar; /// One of the JSExnType constants exnType: int16; /// zero-based column index in line column: uintN; end; /// map an internal structure used to report JavaScript errors PJSErrorReport = ^JSErrorReport; /// callback prototype for reporting error for a given runtime context JSErrorReporter = procedure(cx: PJSContext; _message: PCChar; report: PJSErrorReport); cdecl; /// Possible exception types ................................................................................ JSVAL_TYPE_INT32 = Byte($01); JSVAL_TYPE_UNDEFINED= Byte($02); JSVAL_TYPE_BOOLEAN = Byte($03); JSVAL_TYPE_MAGIC = Byte($04); JSVAL_TYPE_STRING = Byte($05); JSVAL_TYPE_NULL = Byte($06); JSVAL_TYPE_OBJECT = Byte($07); //JSValueTag {$IFDEF CPU32} type JSValueTag = Cardinal; const JSVAL_TAG_CLEAR = Cardinal($FFFFFF80); JSVAL_TAG_INT32 = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_INT32); JSVAL_TAG_UNDEFINED = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_UNDEFINED); JSVAL_TAG_STRING = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_STRING); JSVAL_TAG_BOOLEAN = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_BOOLEAN); JSVAL_TAG_MAGIC = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_MAGIC); JSVAL_TAG_NULL = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_NULL); JSVAL_TAG_OBJECT = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_OBJECT); {$ELSE} //CPU64 type JSValueTag = Cardinal; const JSVAL_TAG_MAX_DOUBLE= Cardinal($0001FFF0); JSVAL_TAG_INT32 = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_INT32); JSVAL_TAG_UNDEFINED = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_UNDEFINED); ................................................................................ JSVAL_SHIFTED_TAG_OBJECT = QWord(JSVAL_TAG_OBJECT) shl JSVAL_TAG_SHIFT; {$ENDIF} JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET = JSVAL_TYPE_NULL; JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET = JSVAL_TYPE_OBJECT; JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET = JSVAL_TYPE_INT32; JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET = JSVAL_TYPE_MAGIC; {$ifdef CPU32} //#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type))) JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET = JSVAL_TAG_NULL; JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET = JSVAL_TAG_OBJECT; JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET = JSVAL_TAG_INT32; JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET = JSVAL_TAG_STRING; {$else} // CPU64 JSVAL_PAYLOAD_MASK : QWord = $00007FFFFFFFFFFF; JSVAL_TAG_MASK : QWord = $FFFF800000000000; JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET = JSVAL_SHIFTED_TAG_NULL; JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET = JSVAL_SHIFTED_TAG_OBJECT; JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET = JSVAL_SHIFTED_TAG_UNDEFINED; JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET = JSVAL_SHIFTED_TAG_STRING; {$endif} type JSWhyMagic = ( JS_ELEMENTS_HOLE, // a hole in a native object's elements JS_NATIVE_ENUMERATE, // indicates that a custom enumerate hook forwarded // to JS_EnumerateState, which really means the object can be // enumerated like a native object. JS_NO_ITER_VALUE, // there is not a pending iterator value JS_GENERATOR_CLOSING, // exception value thrown when closing a generator JS_NO_CONSTANT, // compiler sentinel value JS_THIS_POISON, // used in debug builds to catch tracing errors JS_ARG_POISON, // used in debug builds to catch tracing errors JS_SERIALIZE_NO_NODE, // an empty subnode in the AST serializer JS_LAZY_ARGUMENTS, // lazy arguments value on the stack JS_OPTIMIZED_ARGUMENTS, // optimized-away 'arguments' value JS_IS_CONSTRUCTING, // magic value passed to natives to indicate construction JS_OVERWRITTEN_CALLEE, // arguments.callee has been overwritten JS_FORWARD_TO_CALL_OBJECT, // args object element stored in call object JS_BLOCK_NEEDS_CLONE, // value of static block object slot JS_HASH_KEY_EMPTY, // see class js::HashableValue JS_ION_ERROR, // error while running Ion code JS_ION_BAILOUT, // status code to signal EnterIon will OSR into Interpret JS_GENERIC_MAGIC // for local use ); // here must be jsval_layout struct defenition and *_IMPL functions // but it moved to implementation part of unit, because used only internaly ................................................................................ JSVAL_NULL : QWord = QWord((QWord(JSVAL_TAG_NULL) shl CPU_SHIFT) or 0); JSVAL_ZERO : QWord = QWord((QWord(JSVAL_TAG_INT32) shl CPU_SHIFT) or 0); JSVAL_ONE : QWord = QWord((QWord(JSVAL_TAG_INT32) shl CPU_SHIFT) or 1); JSVAL_FALSE : QWord = QWord((QWord(JSVAL_TAG_BOOLEAN) shl CPU_SHIFT) or JS_FALSE); JSVAL_TRUE : QWord = QWord((QWord(JSVAL_TAG_BOOLEAN) shl CPU_SHIFT) or JS_TRUE); JSVAL_VOID : QWord = QWord((QWord(JSVAL_TAG_UNDEFINED) shl CPU_SHIFT) or 0); type jsint = JSInt32; jsuint = JSUInt32; //#define JSVAL_BITS(v) ((v).asBits) //#define JSVAL_FROM_LAYOUT(l) (l) //#define IMPL_TO_JSVAL(v) (v) ................................................................................ // A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or // JS_IdToValue must be used instead. const JSID_TYPE_STRING = $0; JSID_TYPE_INT = $1; JSID_TYPE_VOID = $2; JSID_TYPE_OBJECT = $4; JSID_TYPE_MASK = $7; //TODO make jsid macro conversion jsapi.h line 308-462 //#define JSVAL_LOCK(cx,v) (JSVAL_IS_GCTHING(v) \ // ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v)) \ // : JS_TRUE) //#define JSVAL_UNLOCK(cx,v) (JSVAL_IS_GCTHING(v) \ ................................................................................ property; don't copy the property on set of the same-named property in an object that delegates to a prototype containing this property } JSPROP_INDEX = $80; { name is actually (jsint) index } JSPROP_SHORTID = $100; { set in JSPropertyDescriptor.attrs if getters/setters use a shortid } JSFUN_STUB_GSOPS = $200; { use JS_PropertyStub getter/setter instead of defaulting to class gsops for property holding function } JSFUN_CONSTRUCTOR = $400; { native that can be called as a ctor } {* * Specify a generic native prototype methods, i.e., methods of a class * prototype that are exposed as static methods taking an extra leading * argument: the generic |this| parameter. * * If you set this flag in a JSFunctionSpec struct's flags initializer, then * that struct must live at least as long as the native static method object * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically * JSFunctionSpec structs are allocated in static arrays. } JSFUN_GENERIC_NATIVE =$800; JSFUN_FLAGS_MASK =$e00; { | of all the JSFUN_* flags } function JS_Now: int64; cdecl; external SpiderMonkeyLib; function JS_GetNaNValue(cx: PJSContext): jsval; cdecl; external SpiderMonkeyLib; function JS_GetNegativeInfinityValue(cx: PJSContext): jsval; cdecl; external SpiderMonkeyLib; function JS_GetPositiveInfinityValue(cx: PJSContext): jsval; cdecl; external SpiderMonkeyLib; function JS_GetEmptyStringValue(cx: PJSContext): jsval; cdecl; external SpiderMonkeyLib; function JS_GetEmptyString(cx: PJSRuntime): PJSString; cdecl; external SpiderMonkeyLib; ................................................................................ // - SameValue slightly differs from strict equality (===) in that +0 and -0 are // not the same and in that NaN is the same as NaN function JS_SameValue(cx: PJSContext; v1, v2: jsval; equal: PJSBool): JSBool; cdecl; external SpiderMonkeyLib; //***************************************************************************** //* Initialization, locking, contexts, and memory allocation //***************************************************************************** // It is important that the first runtime and first context be created in a // single-threaded fashion, otherwise the behavior of the library is undefined // See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference // some aliases defined in SM: // #define JS_NewRuntime JS_Init // #define JS_DestroyRuntime JS_Finish // #define JS_LockRuntime JS_Lock // #define JS_UnlockRuntime JS_Unlock type /// defines how function JS_NewRuntime() instantiate its threading model JSUseHelperThreads = (JS_NO_HELPER_THREADS, JS_USE_HELPER_THREADS); /// Initialize the JavaScript runtime // - JS_NewRuntime initializes the JavaScript runtime environment. // Call JS_NewRuntime before making any other API calls. // - JS_NewRuntime allocates memory for the JSRuntime and initializes certain // internal runtime structures. maxbytes specifies the number of allocated // bytes after which garbage collection is run. function JS_NewRuntime(maxbytes: uint32; useHelperThreads: JSUseHelperThreads): PJSRuntime; cdecl; external SpiderMonkeyLib; /// Release the JavaScript runtime procedure JS_DestroyRuntime(rt: PJSRuntime); cdecl; external SpiderMonkeyLib; /// Free all resources used by the JS engine, not associated with specific runtimes procedure JS_ShutDown; function JS_GetRuntimePrivate(rt: PJSRuntime): pointer; cdecl; external SpiderMonkeyLib; procedure JS_SetRuntimePrivate(rt: PJSRuntime; data: pointer); cdecl; external SpiderMonkeyLib; ................................................................................ function JS_ContextIterator(rt: PJSRuntime; iterp: PPJSContext): PJSContext; cdecl; external SpiderMonkeyLib; /// retrieve the JavaScript version number used within a specified executable script context function JS_GetVersion(cx: PJSContext): JSVersion; cdecl; external SpiderMonkeyLib; // JS_SetVersion is not supported now Use CompartmentOptions in JS_NewGlobalObject /// retrieve the JavaScript version text used within a specified executable script context function JS_VersionToString(version: JSVersion): PCChar; cdecl; external SpiderMonkeyLib; /// configure a JSContext to use a specific version of the JavaScript language function JS_StringToVersion(_string: PCChar): JSVersion; cdecl; external SpiderMonkeyLib; const JSOPTION_EXTRA_WARNINGS = 1 shl 0; { warn on dubious practice } JSOPTION_WERROR = 1 shl 1; { convert warning to error } JSOPTION_VAROBJFIX = 1 shl 2; { make JS_EvaluateScript use the last object on its 'obj' params scope chain as the ECMA 'variables object' } JSOPTION_PRIVATE_IS_NSISUPPORTS = 1 shl 3; { context private data points to an nsISupports subclass } JSOPTION_COMPILE_N_GO = 1 shl 4; { caller of JS_Compile*Script promises to execute compiled script once only; enables compile-time scope chain resolution of consts. } { = 1 shl 5 is currently unused. } { = 1 shl 6 is currently unused. } { = 1 shl 7 is currently unused. } JSOPTION_DONT_REPORT_UNCAUGHT = 1 shl 8; { When returning from the outermost API call, prevent uncaught exceptions from being converted to error reports } { = 1 shl 9 is currently unused. } { = 1 shl 10 is currently unused. } { = 1 shl 11 is currently unused. } JSOPTION_NO_SCRIPT_RVAL = 1 shl 12; { A promise to the compiler that a null rval out-param will be passed to each call to JS_ExecuteScript. } JSOPTION_UNROOTED_GLOBAL = 1 shl 13; { The GC will not root the contexts' global objects (see JS_GetGlobalObject), leaving that up to the embedding. } JSOPTION_BASELINE = 1 shl 14; { Baseline compiler. } JSOPTION_PCCOUNT = 1 shl 15; { Collect per-op execution counts } JSOPTION_TYPE_INFERENCE = 1 shl 16; { Perform type inference. } JSOPTION_STRICT_MODE = 1 shl 17; { Provides a way to force strict mode for all code without requiring "use strict" annotations. } JSOPTION_ION = 1 shl 18; { IonMonkey } JSOPTION_ASMJS = 1 shl 19; { optimizingasm.js compiler } JSOPTION_MASK = 1 shl 20 - 1; function JS_GetOptions(cx: PJSContext): uint32; cdecl; external SpiderMonkeyLib; function JS_SetOptions(cx: PJSContext; options: uint32): uint32; cdecl; external SpiderMonkeyLib; function JS_ToggleOptions(cx: PJSContext; options: uint32): uint32; cdecl; external SpiderMonkeyLib; function JS_GetImplementationVersion: PCChar; cdecl; external SpiderMonkeyLib ; // here is some *Compartment* functions - Compartment is obsolete, so we do not import them ................................................................................ cdecl; external SpiderMonkeyLib; procedure JS_free(cx: PJSContext; p: Pointer); cdecl; external SpiderMonkeyLib; procedure JS_updateMallocCounter(cx: PJSContext; nbytes: size_t); cdecl; external SpiderMonkeyLib; function JS_strdup(cx: PJSContext; s: PCChar): PCChar; cdecl; external SpiderMonkeyLib; //JS_NewNumberValue Obsolete since JavaScript mozjs17 use JS_NumberValue instead //https://developer.mozilla.org/en-US/docs/SpiderMonkey/JSAPI_Reference/JS_NewNumberValue function JS_NumberValue(d: double): jsval; cdecl; external SpiderMonkeyLib name 'JS_NumberValue_'; /// The JS_Add*Root functions add a C/C++ variable to the garbage collector's root set, // the set of variables used as starting points each time the collector checks // to see what memory is reachable // - The garbage collector aggressively collects // and recycles memory that it deems unreachable, so roots are often necessary // to protect data from being prematurely collected. ................................................................................ cdecl; external SpiderMonkeyLib; function JS_AddGCThingRoot(cx: PJSContext; rp: PPointer): JSBool; cdecl; external SpiderMonkeyLib; function JS_RemoveGCThingRoot(cx: PJSContext; rp: PPointer): JSBool; cdecl; external SpiderMonkeyLib; /// launch the GarbageCollection process of the given execution RunTime procedure JS_GC(rt: PJSRuntime); cdecl; external SpiderMonkeyLib; /// check if it would be worth it to launch the GarbageCollection process // of the given execution RunTime, in the given context // - this function is a no-op if there is nothing interesting to garbage procedure JS_MaybeGC(cx: PJSContext); cdecl; external SpiderMonkeyLib; /// defines a Garbage Collection call-back function function JS_SetGCCallback(rt: PJSRuntime; cb: JSGCCallback): JSGCCallback; cdecl; external SpiderMonkeyLib; /// JS_IsAboutToBeFinalized(� checks if the given object is going to be finalized // at the end of the current GC // - When called outside of the context of a GC, this function will return false // - Typically this function is used on weak references, where the reference // should be nulled out or destroyed if the given object is about to be finalized // - The argument to JS_IsAboutToBeFinalized is an in-out param: when the // function returns false, the object being referenced is still alive, but the // garbage collector might have moved it. In this case, the reference passed // to JS_IsAboutToBeFinalized will be updated to the object's new location // - Callers of this method are responsible for updating any state that is // dependent on the object's address. For example, if the object's address is // used as a key in a hashtable, then the object must be removed and // re-inserted with the correct hash function JS_IsAboutToBeFinalized(obj: PPJSObject): JSBool; cdecl; external SpiderMonkeyLib; type JSGCParamKey = ( // Maximum nominal heap before last ditch GC. JSGC_MAX_BYTES = 0, // Number of JS_malloc bytes before last ditch GC. JSGC_MAX_MALLOC_BYTES = 1, // Obsolete since JSAPI 12 JSGC_STACKPOOL_LIFESPAN = 2, // Obsolete since JSAPI 6 JSGC_TRIGGER_FACTOR = 3, //* Amount of bytes allocated by the GC. */ JSGC_BYTES = 3, //* Number of times when GC was invoked. */ JSGC_NUMBER = 4, //* Max size of the code cache in bytes. */ JSGC_MAX_CODE_CACHE_BYTES = 5, //* Select GC mode. */ JSGC_MODE = 6, //* Number of GC chunks waiting to expire. */ JSGC_UNUSED_CHUNKS = 7, //* Total number of allocated GC chunks. */ JSGC_TOTAL_CHUNKS = 8, //* Max milliseconds to spend in an incremental GC slice. */ JSGC_SLICE_TIME_BUDGET = 9, //* Maximum size the GC mark stack can grow to. */ JSGC_MARK_STACK_LIMIT = 10, (* * GCs less than this far apart in time will be considered 'high-frequency GCs'. * See setGCLastBytes in jsgc.cpp. *) JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11, (* Start of dynamic heap growth. *) JSGC_HIGH_FREQUENCY_LOW_LIMIT = 12, (* End of dynamic heap growth. *) JSGC_HIGH_FREQUENCY_HIGH_LIMIT = 13, (* Upper bound of heap growth. *) JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX = 14, (* Lower bound of heap growth. *) JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN = 15, (* Heap growth for low frequency GCs. *) JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16, (* * If false, the heap growth factor is fixed at 3. If true, it is determined * based on whether GCs are high- or low- frequency. *) JSGC_DYNAMIC_HEAP_GROWTH = 17, (* If true, high-frequency GCs will use a longer mark slice. *) JSGC_DYNAMIC_MARK_SLICE = 18, (* Number of megabytes of analysis data to allocate before purging. *) JSGC_ANALYSIS_PURGE_TRIGGER = 19, (* Lower limit after which we limit the heap growth. *) JSGC_ALLOCATION_THRESHOLD = 20, (* * We decommit memory lazily. If more than this number of megabytes is * available to be decommitted, then JS_MaybeGC will trigger a shrinking GC * to decommit it. *) JSGC_DECOMMIT_THRESHOLD = 21 ); JSGCMode = ( //* Perform only global GCs. */ JSGC_MODE_GLOBAL = 0, //* Perform per-compartment GCs until too much garbage has accumulated. */ JSGC_MODE_COMPARTMENT = 1, //* Collect in short time slices rather than all at once. Implies // * JSGC_MODE_COMPARTMENT. JSGC_MODE_INCREMENTAL = 2 ); procedure JS_SetGCParameter(rt: PJSRuntime; key: JSGCParamKey; value: uint32); cdecl; external SpiderMonkeyLib; function JS_GetGCParameter(rt: PJSRuntime; key: JSGCParamKey): uint32; cdecl; external SpiderMonkeyLib; ................................................................................ cdecl; external SpiderMonkeyLib; /// Flush the code cache for the current thread // - The operation might be delayed if the cache cannot be flushed currently // because native code is currently executing. procedure JS_FlushCaches(cx: PJSContext); cdecl; external SpiderMonkeyLib; type /// * Finalizes external strings created by JS_NewExternalString. PJSStringFinalizer = ^JSStringFinalizer; JSStringFinalizerOp = procedure(fin: PJSStringFinalizer; chars: Pjschar); cdecl; JSStringFinalizer = record finalize: JSStringFinalizerOp; end; /// Creates a new JSString whose characters are stored in external memory, i.e., // memory allocated by the application, not the JavaScript engine // - Since the program allocated the memory, it will need to free it; // this happens in an external string finalizer indicated by the type parameter. // - chars is Pointer to the first element of an array of jschars. // This array is used as the character buffer of the JSString to be created. // The array must be populated with the desired character data before JS_NewExternalString // is called, and the array must remain in memory, with its contents unchanged, // for as long as the JavaScript engine needs to hold on to it. // (Ultimately, the string will be garbage collected, and the JavaScript engine will // call the string finalizer callback, allowing the application to free the array) // - The text buffer array does not need to be zero-terminated. function JS_NewExternalString(cx: PJSContext; chars: pjschar; length: size_t; const fin: PJSStringFinalizer): PJSString; cdecl; external SpiderMonkeyLib; /// Returns the external-string finalizer index for this string, or -1 if it is // an "internal" (native to JS engine) string. //TODO - in current compiled version there is no this functions. seems like a BUG!!!!!!!! //JS_GetExternalStringGCType //function JS_IsExternalString(rt: PJSRuntime; str: PJSString): intN; cdecl; external SpiderMonkeyLib; ................................................................................ JSClassInternal = procedure; cdecl; PJSClass = ^JSClass; JSClass = record name: PCChar; flags: uint32; //* Mandatory non-null function pointer members. */ addProperty: JSPropertyOp; delProperty: JSDeletePropertyOp; getProperty: JSPropertyOp; setProperty: JSStrictPropertyOp; enumerate: pointer; //JSEnumerateOp; or JSNewEnumerateOp resolve: JSResolveOp; convert: JSConvertOp; //* Optionally non-null members start here. */ finalize: JSFinalizeOp; { in jsapi.h file comments finalize is Mandatory but in real it is Optionally in examles finalize is not assigned } checkAccess: JSCheckAccessOp; call: JSNative; hasInstance: JSHasInstanceOp; construct: JSNative; trace: JSTraceOp; reserved: array [0..39] of pointer; end; const /// JSClass instance objects have private slot JSCLASS_HAS_PRIVATE = 1 shl 0; /// JSClass instance has JSNewEnumerateOp hook JSCLASS_NEW_ENUMERATE = 1 shl 1; /// JSClass instance has JSNewResolveOp hook JSCLASS_NEW_RESOLVE = 1 shl 2; /// JSClass instance private is (nsISupports JSCLASS_PRIVATE_IS_NSISUPPORTS = 1 shl 3; /// JSClass instance objects are DOM JSCLASS_IS_DOMJSCLASS = 1 shl 4; /// Correctly implements GC read and write barriers JSCLASS_IMPLEMENTS_BARRIERS = 1 shl 5; /// JSClass instance objects of this class act like the value undefined, // in some contexts JSCLASS_EMULATES_UNDEFINED = 1 shl 6; /// Reserved for embeddings. JSCLASS_USERBIT1 = 1 shl 7; /// JSClass instance room for 8 flags below JSCLASS_RESERVED_SLOTS_SHIFT = 8; /// JSClass instance and 16 above this field JSCLASS_RESERVED_SLOTS_WIDTH = 8; JSCLASS_RESERVED_SLOTS_MASK = (JSUint32(1) shl JSCLASS_RESERVED_SLOTS_WIDTH)-1; JSCLASS_HIGH_FLAGS_SHIFT = (JSCLASS_RESERVED_SLOTS_SHIFT + JSCLASS_RESERVED_SLOTS_WIDTH); JSCLASS_IS_ANONYMOUS = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+0)); JSCLASS_IS_GLOBAL = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+1)); JSCLASS_INTERNAL_FLAG2 = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+2)); JSCLASS_INTERNAL_FLAG3 = (1 shl (JSCLASS_HIGH_FLAGS_SHIFT+3)); // JSProto_LIMIT is length of #include "jsproto.tbl" JSProto_LIMIT = 38; JSCLASS_GLOBAL_SLOT_COUNT = (JSProto_LIMIT * 3 + 25); JSCLASS_GLOBAL_FLAGS = JSCLASS_IS_GLOBAL or (((JSCLASS_GLOBAL_SLOT_COUNT) and JSCLASS_RESERVED_SLOTS_MASK) shl JSCLASS_RESERVED_SLOTS_SHIFT); procedure JS_DestroyIdArray(cx: PJSContext; ida: PJSIdArray); cdecl; external SpiderMonkeyLib; function JS_ValueToId(cx: PJSContext; v: jsval; var id: jsid): JSBool; cdecl; external SpiderMonkeyLib; function JS_IdToValue(cx: PJSContext; id: jsid; var v: jsval): JSBool; cdecl; external SpiderMonkeyLib; ................................................................................ JSRESOLVE_DECLARING = $08; /// used by JS_ResolveStub() callback: class name used when constructing JSRESOLVE_CLASSNAME = $10; /// used by JS_ResolveStub() callback: resolve inside a with statement JSRESOLVE_WITH = $20; /// default callback matching JSPropertyOp prototype of JSClass function JS_PropertyStub(cx: PJSContext; var obj: PJSObject; var id: jsid; vp: pjsval): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSStrictPropertyOp prototype of JSClass function JS_StrictPropertyStub(cx: PJSContext; var obj: PJSObject; var id: jsid; _strict: JSBool; vp: pjsval): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSEnumerateOp prototype of JSClass function JS_EnumerateStub(cx: PJSContext; var obj: PJSObject): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSResolveOp prototype of JSClass function JS_ResolveStub(cx: PJSContext; var obj: PJSObject; var id: jsid): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSConvertOp prototype of JSClass function JS_ConvertStub(cx: PJSContext; var obj: PJSObject; _type: JSType; vp: pjsval): JSBool; cdecl; external SpiderMonkeyLib; /// default callback matching JSDeletePropertyOp prototype of JSClass function JS_DeletePropertyStub(cx: PJSContext; var obj: PJSObject; var id: jsid; succeeded: PJSBool): JSBool; cdecl; external SpiderMonkeyLib; type /// JS object constant definition JSConstDoubleSpec = record dval: jsdouble; name: PCChar; flags: uint8; spare: array[0..2] of uint8; end; PJSConstDoubleSpec = ^JSConstDoubleSpec; TJSConstDoubleSpecArray = array of JSConstDoubleSpec; /// JS object property defenition PJSJitInfo = pointer; ///* // * Wrappers to replace {Strict,}PropertyOp for JSPropertySpecs. This will allow // * us to pass one JSJitInfo per function with the property spec, without // * additional field overhead. JSStrictPropertyOpWrapper = record op: JSStrictPropertyOp; info: PJSJitInfo; end; JSPropertyOpWrapper = record op: JSPropertyOp; info: PJSJitInfo; end; JSPropertySpec = record name: PCChar; tinyid: int8; flags: uint8; getter: JSPropertyOpWrapper; setter: JSStrictPropertyOpWrapper; end; PJSPropertySpec = ^JSPropertySpec; TJSPropertySpecArray = array of JSPropertySpec; /// * Wrapper to do as above, but for JSNatives for JSFunctionSpecs. JSNativeWrapper = record op: JSNative; info: PJSJitInfo; end; /// Defines a single function for an object. JSFunctionSpec = record name: PCChar; call: JSNativeWrapper; nargs: uint16; flags: uint16; selfHostedName: PCChar; end; PJSFunctionSpec = ^JSFunctionSpec; TJSFunctionSpecArray = array of JSFunctionSpec; /// Make a JSClass accessible to JavaScript code by creating its prototype, // constructor, properties, and functions. // - see https://developer.mozilla.org/en-US/docs/SpiderMonkey/JSAPI_Reference/JS_InitClass function JS_InitClass(cx: PJSContext; obj: PJSObject; parent_proto: PJSObject; clasp: PJSClass; _constructor: JSNative; nargs: uintN; ps: PJSPropertySpec; fs: PJSFunctionSpec; static_ps: PJSPropertySpec; static_fs: PJSFunctionSpec): PJSObject; cdecl; external SpiderMonkeyLib ; /// retrieve the JSClass of a given object // - JS_GetClass() expects only one parameter in every case function JS_GetClass(obj: PJSObject): PJSClass; cdecl; external SpiderMonkeyLib name 'JS_GetClass'; function JS_InstanceOf(cx: PJSContext; obj: PJSObject; clasp: PJSClass; argv: pjsval): JSBool; cdecl; external SpiderMonkeyLib; function JS_HasInstance(cx: PJSContext; obj: PJSObject; v: jsval; bp: PJSBool): JSBool; cdecl; external SpiderMonkeyLib; function JS_GetPrivate(obj: PJSObject): Pointer; cdecl; external SpiderMonkeyLib; procedure JS_SetPrivate(obj: PJSObject; data: Pointer); cdecl; external SpiderMonkeyLib; function JS_GetInstancePrivate(cx: PJSContext; obj: PJSObject; clasp: PJSClass; argv: pjsval): Pointer; cdecl; external SpiderMonkeyLib; function JS_GetPrototype(cx: PJSContext; obj: PJSObject; var protop: PJSObject):JSBool; cdecl; external SpiderMonkeyLib; function JS_SetPrototype(cx: PJSContext; obj: PJSObject; proto: PJSObject): JSBool; cdecl; external SpiderMonkeyLib; function JS_GetParent(obj: PJSObject): PJSObject; cdecl; external SpiderMonkeyLib; function JS_SetParent(cx: PJSContext; obj: PJSObject; parent: PJSObject): JSBool; cdecl; external SpiderMonkeyLib; function JS_GetConstructor(cx: PJSContext; proto: PJSObject): PJSObject; cdecl; external SpiderMonkeyLib; /// Get a unique identifier for obj, good for the lifetime of obj (even if it // is moved by a copying GC) // - Return false on failure (likely out of memory), and true with idp // containing the unique id on success function JS_GetObjectId(cx: PJSContext; obj: PJSObject; idp: Pjsid): JSBool; cdecl; external SpiderMonkeyLib; type ZoneSpecifier = JSuintptr; const zsFreshZone = JSuintptr(0); zsSystemZone = JSuintptr(1); zsSpecificZones = JSuintptr(2); type CompartmentOptions = record zoneSpec: ZoneSpecifier; hasVersion: boolean; version: JSVersion; end; PCompartmentOptions = ^CompartmentOptions; /// JS_NewGlobalObject creates a new global object based on the specified class // - The new object has no parent. It initially has no prototype either, // since it is typically the first object created; // call JS_InitStandardClasses to create all the standard objects, // including Object.prototype, and set the global object's prototype function JS_NewGlobalObject(cx: PJSContext; clasp: PJSClass; principals: PJSPrincipals; options: PCompartmentOptions): PJSObject; cdecl; external SpiderMonkeyLib; /// declare entering a safe compartment of the specified object // - NB: This API is infallible; a NULL return value does not indicate error function JS_EnterCompartment(cx: PJSContext; target: PJSObject): PJSCompartment; cdecl; external SpiderMonkeyLib; /// declare leaving the safe compartment of the specified object procedure JS_LeaveCompartment(cx: PJSContext; oldCompartment: PJSCompartment); cdecl; external SpiderMonkeyLib; /// JS_NewObject creates a new object based on a specified class, prototype, // and parent object // - cx is a pointer to a context associated with the runtime // in which to establish the new object. // - clasp is a pointer to an existing class to use for internal methods, such as finalize // - proto is an optional pointer to the prototype object with which to associate the new object ................................................................................ id: jsid; flags: uintN; var objp: PJSObject; var vp: jsval): JSBool; cdecl; external SpiderMonkeyLib; type JSPropertyDescriptor = record obj: PJSObject; attrs: uintN; shortid: uintN; getter: JSPropertyOp; setter: JSStrictPropertyOp; value: jsval; end; PJSPropertyDescriptor = ^JSPropertyDescriptor; /// Finds a specified property of an object and gets a detailed description of that property function JS_GetPropertyDescriptorById(cx: PJSContext; obj: PJSObject; id: jsid; flags: uintN; objp: PPJSObject; desc: PJSPropertyDescriptor): JSBool; cdecl; external SpiderMonkeyLib; ................................................................................ cdecl; external SpiderMonkeyLib ; /// Unicode version to compiles a script function JS_CompileUCScript(cx: PJSContext; obj: PJSObject; chars: Pjschar; length: size_t; filename: PCChar; lineno: uintN): PJSScript; cdecl; external SpiderMonkeyLib ; type TCStringVector = array[0..0] of PCChar; PCStringVector = ^TCStringVector; /// JS_CompileFunction compiles a function from a text string, bytes, and // optionally associates it with a JS object, obj ................................................................................ /// retrieve the callback function that is automatically called periodically while // JavaScript code runs in the given execution context function JS_GetOperationCallback(cx: PJSContext): JSOperationCallback; cdecl; external SpiderMonkeyLib; /// triggers a callback set using JS_SetOperationCallback procedure JS_TriggerOperationCallback(rt: PJSRuntime); cdecl; external SpiderMonkeyLib; /// determines if a script or function is currently executing in a specified // JSContext, cx // - If a script is executing, JS_IsRunning returns JS_TRUE // - Otherwise it returns JS_FALSE. function JS_IsRunning(cx: PJSContext): JSBool; cdecl; external SpiderMonkeyLib; ................................................................................ 1: (u32: uint32); 2: (boo: JSBool); 3: (str: PJSString); 4: (obj: PJSObject); 5: (ptr: pointer); 6: (why: JSWhyMagic); 7: (word: jsuword); 8: (uintptr: JSuintptr) end; {$ifdef IS_LITTLE_ENDIAN} jsval_val_layout = packed record payload: jsval_payload; tag: JSValueTag; end; {$else} //BIG_ENDIAN ................................................................................ case Byte of 0: (asBits: QWord); 1: (s: jsval_val_layout); 2: (asDouble: double); 3: (asPtr: Pointer); end; //****************************************************************************** // NSPR library APIs //****************************************************************************** const /// numbers of micro secs per second PRMJ_USEC_PER_SEC = 1000000; /// stipulate that the process should wait no time as defined by NSPR // - i.e. will return immediately // - defined in the PRIntervalTime namespace PR_INTERVAL_NO_WAIT =$0; /// stipulate that the process should wait forever as defined by NSPR // - i.e. will never time out // - defined in the PRIntervalTime namespace PR_INTERVAL_NO_TIMEOUT =$ffffffff; type /// unsigned 32 bit integer type as defined by NSPR PRUint32 = uint32; /// interval time type as defined by NSPR PRIntervalTime = PRUint32; /// a mutex/lock resource as defined by NSPR PRLock = Pointer; /// a event resource as defined by NSPR PRCondVar = Pointer; /// a thread resource as defined by NSPR PRThread = Pointer; /// status codes as defined by NSPR PRStatus = (PR_FAILURE = -1, PR_SUCCESS = 0); /// thread type as defined by NSPR PRThreadType = (PR_USER_THREAD, PR_SYSTEM_THREAD); /// thread priority as defined by NSPR // - PR_PRIORITY_LOW is the lowest possible priority // - PR_PRIORITY_NORMAL is the most common expected priority // - PR_PRIORITY_HIGH is the slightly more aggressive scheduling // - PR_PRIORITY_URGENT is there because it does little good to have one // more priority value PRThreadPriority = ( PR_PRIORITY_FIRST = 0, PR_PRIORITY_LOW = 0, PR_PRIORITY_NORMAL = 1, PR_PRIORITY_HIGH = 2, PR_PRIORITY_URGENT = 3, PR_PRIORITY_LAST = 3); /// thread scope as defined by NSPR PRThreadScope = (PR_LOCAL_THREAD, PR_GLOBAL_THREAD, PR_GLOBAL_BOUND_THREAD); /// thread state as defined by NSPR PRThreadState = (PR_JOINABLE_THREAD, PR_UNJOINABLE_THREAD); /// allocates a new NSPR mutex/lock function PR_NewLock: PRLock; cdecl; external NSPRLib; /// allocates a new NSPR event function PR_NewCondVar(lock: PRLock): PRCondVar; cdecl; external NSPRLib; /// free a previously allocated NSPR event procedure PR_DestroyCondVar(cvar: PRCondVar); cdecl; external NSPRLib; /// notify a previously allocated NSPR event function PR_NotifyCondVar(cvar: PRCondVar): PRStatus; cdecl; external NSPRLib; /// notify all previously allocated NSPR event function PR_NotifyAllCondVar(cvar: PRCondVar): PRStatus; cdecl; external NSPRLib; /// wait until a previously allocated NSPR event is notified function PR_WaitCondVar(cvar: PRCondVar; timeout: PRIntervalTime): PRStatus; cdecl; external NSPRLib; /// enter a previously allocated NSPR mutex/lock procedure PR_Lock(lock: PRLock); cdecl; external NSPRLib; /// leave a previously allocated NSPR mutex/lock function PR_Unlock(lock: PRLock): PRStatus; cdecl; external NSPRLib; /// free a previously allocated NSPR lock procedure PR_DestroyLock(lock: PRLock); cdecl; external NSPRLib; /// join a NSPR thread function PR_JoinThread(thred: PRThread): PRStatus; cdecl; external NSPRLib; /// initializes a NSPR thread function PR_CreateThread( type_: PRThreadType; start: pointer; arg: pointer; priority: PRThreadPriority; scope: PRThreadScope; state: PRThreadState; stackSize: PRUint32): PRThread; cdecl; external NSPRLib; /// change the current NSPR thread name function PR_SetCurrentThreadName(name: PAnsiChar): PRStatus; cdecl; external NSPRLib; /// returns the number of ticks per seconds as expected by NSPR function PR_TicksPerSecond(): PRUint32; cdecl; external NSPRLib; //****************************************************************************** // Debugger //****************************************************************************** /// enables the JavaScript debugging mode for a given runtime procedure JS_SetRuntimeDebugMode(rt: PJSRuntime; debug: JSBool); cdecl; external SpiderMonkeyLib; /// enables the JavaScript debugging mode for a given context function JS_SetDebugMode(cx: PJSContext; debug: JSBool): JSBool; cdecl; external SpiderMonkeyLib; /// check if the JavaScript debugging mode is set for a given context function JS_GetDebugMode(cx: PJSContext): JSBool; cdecl; external SpiderMonkeyLib; type /// callback type to be called when debugging a JavaScript context JSNewScriptHook = procedure(cx: PJSContext; filename: PCChar; lineno: uintn; script:PJSScript; fun: PJSFunction; callerdata: pointer); cdecl; /// set a JavaScript debugging hook callback procedure JS_SetNewScriptHookProc(rt: PJSRuntime; hook: JSNewScriptHook; callerdata: Pointer); cdecl; external SpiderMonkeyLib; type /// calback type to be called when an operation is freed PJSFreeOp = Pointer; /// calback type to be called when a JavaScript debugging hook is released JSDestroyScriptHook = procedure(fop: PJSFreeOp; script: PJSScript; callerdata: Pointer); cdecl; /// set the callback to be called when a JavaScript debugging hook is released procedure JS_SetDestroyScriptHookProc(rt: PJSRuntime; hook: JSDestroyScriptHook; callerdata: Pointer); cdecl; external SpiderMonkeyLib; type /// used to store a JavaScript bytecode item jsbytecode = uint8; /// used to store a pointer to JavaScript bytecode items pjsbytecode = ^jsbytecode; /// JavaScript debugging trap status JSTrapStatus = ( JSTRAP_ERROR, JSTRAP_CONTINUE, JSTRAP_RETURN, JSTRAP_THROW, JSTRAP_LIMIT); /// calback type to be called when a script is debugging JSDebuggerHandler = function(cx: PJSContext; script: PJSScript; pc: pjsbytecode; rval: pjsval; closure: pointer): JSTrapStatus; cdecl; /// set a debugging handler callback for a given hook and runtime function JS_SetDebuggerHandler(rt: PJSRuntime; hook: JSDebuggerHandler; closure: pointer): JSBool; cdecl; external SpiderMonkeyLib; type /// calback type to be called when a script is debugging and trapped JSTrapHandler = function(cx: PJSContext; script: PJSScript; pc: pjsbytecode; rval: pjsval; closure: jsval): JSTrapStatus; cdecl; /// set a trap debugging handler callback for a given execution context function JS_SetTrap(cx: PJSContext; script: PJSScript; pc: pjsbytecode; handler: JSTrapHandler; closure: jsval): JSBool; cdecl; external SpiderMonkeyLib; /// clear a trap debugging handler callback for a given execution context procedure JS_ClearTrap(cx: PJSContext; script: PJSScript; pc: pjsbytecode; handler: JSTrapHandler; closure: jsval); cdecl; external SpiderMonkeyLib; type /// calback type to be called when an error is triggerred during script debugging JSDebugErrorHook = function(cx: PJSContext; message: PCChar; report: PJSErrorReport; closure: pointer): JSTrapStatus; cdecl; /// set a calback to be called when an error is triggerred during script debugging function JS_SetDebugErrorHook(rt: PJSRuntime; hook: JSDebugErrorHook; closure: pointer): JSBool; cdecl; external SpiderMonkeyLib; type /// calback type to be called when script debugging is interrupted JSInterruptHook = function(cx: PJSContext; script: PJSScript; pc: pjsbytecode; rval: pjsval; closure: pointer): JSTrapStatus; cdecl; /// set a calback to be called when script debugging is interrupted function JS_SetInterrupt(rt: PJSRuntime; handler: JSInterruptHook; closure: pointer): JSBool; cdecl; external SpiderMonkeyLib; /// clear a calback to be called when script debugging is interrupted function JS_ClearInterrupt(rt: PJSRuntime; hook: JSInterruptHook; closurep: PPointer): JSBool; cdecl; external SpiderMonkeyLib; /// decompile a JavaScript script function JS_DecompileScript(cx: PJSContext; script: PJSScript; name: PCChar; indent: uintn ): PJSString; cdecl; external SpiderMonkeyLib; type /// points to a frame description of a stack trace PFrameDescription = ^FrameDescription; /// defines a frame of a stack trace FrameDescription = record script: PJSScript; lineno: uintn; fun: PJSFunction; end; /// points to a stack trace PStackDescription = ^StackDescription; /// defines a stack trace StackDescription = record nframes: uintn; frames: PFrameDescription; end; /// retrieve the stack trace of a given execution context function DescribeStack(cx: PJSContext; maxFrames: uintn): PStackDescription; cdecl; external SpiderMonkeyLib; /// release the stack trace description of a given execution context procedure FreeStackDescription(cx: PJSContext; desc: PStackDescription); cdecl; external SpiderMonkeyLib; type /// points to an extended frame description of a stack trace PFrameDescriptionEx = ^FrameDescriptionEx; /// defines an extended frame of a stack trace FrameDescriptionEx = record script: PJSScript; lineno: uintn; fun: PJSFunction; callObject: PJSObject; end; /// points to an extended stack trace PStackDescriptionEx = ^StackDescriptionEx; /// defines to an extended stack trace StackDescriptionEx = record nframes: uintn; frames: PFrameDescriptionEX; end; /// retrieve the extended stack trace of a given execution context function DescribeStackEx(cx: PJSContext; maxFrames: uintn): PStackDescriptionEx; cdecl; external SpiderMonkeyLib; /// release the extended stack trace description of a given execution context procedure FreeStackDescriptionEx(cx: PJSContext; desc: PStackDescriptionEx); cdecl; external SpiderMonkeyLib; /// dump stack trace info with the specified format function FormatStackDump(cx: PJSContext; buf: PCChar; showArgs, showLocals, showThisProps: JSBool): PCChar; cdecl; external SpiderMonkeyLib; /// retrieve the script line number from a byte code item position function JS_PCToLineNumber(cx: PJSContext; script: PJSScript; pc: pjsbytecode): uintn; cdecl; external SpiderMonkeyLib; /// retrieve the byte code item position corresponding to a script line number function JS_LineNumberToPC(cx: PJSContext; script: PJSScript; lineno: uintn): pjsbytecode; cdecl; external SpiderMonkeyLib; type /// define object property behavior // - JSPD_ENUMERATE means that the property is visible to for/in loop // - JSPD_READONLY means that the property assignment will trigger an error // - JSPD_PERMANENT means that the property cannot be deleted // - JSPD_ALIAS means that the property has an alias id // - JSPD_EXCEPTION means that an exception occurred fetching the property: // in this case, value is an exception // - JSPD_ERROR means that the native getter returned JS_FALSE without // throwing an exception JSPropertyDescFlag = ( dfEnumerate, dfReadOnly, dfPermanent, dfAlias, dfException, dfError); /// define object property behaviors JSPropertyDescFlags = set of JSPropertyDescFlag; /// points to a JavaScript object property description PJSPropertyDesc = ^JSPropertyDesc; /// defines a JavaScript object property description JSPropertyDesc = record // the ID of this property id: jsval; /// the JavaScript value of this property value: jsval; /// the property behavior flags: JSPropertyDescFlags; /// this item is never used spare_notused: uint8; /// contains the alias ID if dfAlias is included in description flags alias: jsval; end; /// stores JavaScript object properties description JSPropertyDescArray = record len: uint32; arr: PJSPropertyDesc; end; /// retrieve the description of a given JavaScript object property function JS_GetPropertyDescArray(cx: PJSContext; obj: PJSObject; var pda: JSPropertyDescArray): JSBool; cdecl; external SpiderMonkeyLib; /// define the description of a given JavaScript object property procedure JS_PutPropertyDescArray(cx: PJSContext; var pda: JSPropertyDescArray); cdecl; external SpiderMonkeyLib; /// cast a JavaScript function into a script instance function JS_GetFunctionScript(cx: PJSContext; fun: PJSFunction): PJSScript; cdecl; external SpiderMonkeyLib; /// retrieve the local name array information of a given function function JS_GetFunctionLocalNameArray(cx: PJSContext; fun: PJSFunction; var markp: pointer): PJSuintptr; cdecl; external SpiderMonkeyLib; /// release the local name array information of a given function procedure JS_ReleaseFunctionLocalNameArray(cx: PJSContext; markp: pointer); cdecl; external SpiderMonkeyLib; /// retrieves how many arguments expect a function function JS_GetFunctionArgumentCount(cx: PJSContext; fun: PJSFunction): uint; cdecl; external SpiderMonkeyLib; type /// stores a JavaScript Atom PJSAtom = Pointer; /// convert a local name into a JavaScript atom function JS_LocalNameToAtom(w: JSuintptr): PJSAtom; cdecl; external SpiderMonkeyLib; /// retrieve the local name into a JavaScript atom function JS_AtomKey(atom: PJSAtom): PJSString; cdecl; external SpiderMonkeyLib; /// retrieve the base line number of a given script function JS_GetScriptBaseLineNumber(cx: PJSContext; script: PJSScript): uint; cdecl; external SpiderMonkeyLib; /// retrieve the extent of a given script function JS_GetScriptLineExtent(cx: PJSContext; script: PJSScript): uint; cdecl; external SpiderMonkeyLib; implementation // **************************************************************************** // * jsval.h *_IMPL functions * // **************************************************************************** ................................................................................ if JSVAL_IS_OBJECT_IMPL(l) then Result := uint32(JS_FALSE) else Result := uint32(JS_TRUE); end; {$endif} //CPU64 // **************************************************************************** // * jsapi.h functions * // **************************************************************************** function JSVAL_IS_NULL(const v: jsval): Boolean; begin ................................................................................ end; procedure JSContext.SetPrivate(const Value: Pointer); begin JS_SetContextPrivate(@self,Value); end; function JSContext.NewJSString(const Value: RawUTF8): PJSString; begin result := NewJSString(pointer(Value),length(Value),CP_UTF8); end; function JSContext.NewJSString(const Value: SynUnicode): PJSString; begin ................................................................................ function JSObject.ToJSValue: jsval; begin if @self=nil then result := JSVAL_NULL else result := OBJECT_TO_JSVAL(@self); end; { JSCompartment } procedure JSCompartment.Destroy; begin if @self<>nil then JS_LeaveCompartment(fcx,@self); end; function JSCompartment.EnterCompartment(cx: PJSContext; target: PJSObject): PJSCompartment; begin Result := JS_EnterCompartment(cx,target); if Assigned(Result) then Result.fcx := cx; end; // procedure JS_ShutDown; cdecl; external SpiderMonkeyLib; procedure JS_ShutDown; // avoid need of mozjs-24.dll even if not used var Shutdown: procedure; cdecl; begin Shutdown := GetProcAddress(GetModuleHandle(SpiderMonkeyLib),'JS_ShutDown'); if Assigned(Shutdown) then Shutdown; end; initialization assert(1 shl ord(jsoTypeInference)=JSOPTION_TYPE_INFERENCE); assert(1 shl ord(sjpShortID)=JSPROP_SHORTID); finalization JS_ShutDown; end. |