xtool/contrib/mORMot/SyNode/SyNodeBinding_util.pas

175 lines
5.6 KiB
ObjectPascal

/// `util` module support bindings for SyNode
// - this unit is a part of the freeware Synopse framework,
// licensed under a MPL/GPL/LGPL tri-license; version 1.18
unit SyNodeBinding_util;
interface
{$I Synopse.inc}
{$I SyNode.inc}
uses
SysUtils,
SynCommons,
SyNode, SpiderMonkey;
function HasInstance(cx: PJSContext; argc: uintN; var vp: jsargRec; proto: JSProtoKey): Boolean; {$IFNDEF FPC}{$ifdef HASINLINE}inline;{$endif}{$ENDIF}// << this couses internal error on FPC 3.0.2
implementation
///This is dirty hack using Spider Monkey internals
function HasInstance(cx: PJSContext; argc: uintN; var vp: jsargRec; proto: JSProtoKey): Boolean; {$IFNDEF FPC}{$ifdef HASINLINE}inline;{$endif}{$ENDIF}// << this couses internal error on FPC 3.0.2
var
in_argv: PjsvalVector;
slotIndex: uint32;
const
sInvalidCall = 'One argunent required';
begin
Result := False;
try
// {$IFNDEF SM45}
// raise ENotImplemented.Create('Check that slots order is correct and you can continue using this internal');
// {$ENDIF}
in_argv := vp.argv;
if (argc <> 1) then
raise ESMException.Create(sInvalidCall);
slotIndex := JSCLASS_GLOBAL_APPLICATION_SLOTS + Ord(proto);
vp.rval := SimpleVariantToJSval(cx, cx.CurrentGlobalOrNull.ReservedSlot[slotIndex].asObject.HasInstance(cx, in_argv[0]));
Result := True;
except
on E: Exception do begin
vp.rval := JSVAL_VOID;
JSError(cx, E);
end;
end;
end;
function isArrayBuffer(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
begin
Result := HasInstance(cx, argc, vp, JSProto_ArrayBuffer);
end;
function isDataView(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
begin
Result := HasInstance(cx, argc, vp, JSProto_DataView);
end;
function isDate(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
begin
Result := HasInstance(cx, argc, vp, JSProto_Date);
end;
function isMap(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
begin
Result := HasInstance(cx, argc, vp, JSProto_Map);
end;
///This is dirty hack using Spider Monkey internals
function isMapIterator(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
const
sInvalidCall = 'One argunent required';
begin
Result := False;
try
// {$IFNDEF SM45}
// raise ENotImplemented.Create('Check that Class_ name is correct and you can continue using this internal');
// {$ENDIF}
if (argc <> 1) then
raise ESMException.Create(sInvalidCall);
vp.rval := SimpleVariantToJSval(cx,
vp.argv[0].isObject and (vp.argv[0].asObject.Class_.name = 'Map Iterator')
);
Result := True;
except
on E: Exception do begin
vp.rval := JSVAL_VOID;
JSError(cx, E);
end;
end;
end;
/// SyNode not use prommise yet
function isPromise(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
begin
Result := True;
vp.rval := SimpleVariantToJSval(cx,false);
end;
function isRegExp(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
begin
Result := HasInstance(cx, argc, vp, JSProto_RegExp);
end;
function isTypedArray(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
begin
Result := HasInstance(cx, argc, vp, JSProto_Set);
end;
///This is dirty hack using Spider Monkey internals
function isSetIterator(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
const
sInvalidCall = 'One argunent required';
begin
Result := False;
try
// {$IFNDEF SM45}
// raise ENotImplemented.Create('Check that Class_ name is correct and you can continue using this internal');
// {$ENDIF}
if (argc <> 1) then
raise ESMException.Create(sInvalidCall);
vp.rval := SimpleVariantToJSval(cx,
vp.argv[0].isObject and (vp.argv[0].asObject.Class_.name = 'Set Iterator')
);
Result := True;
except
on E: Exception do begin
vp.rval := JSVAL_VOID;
JSError(cx, E);
end;
end;
end;
function isSet(cx: PJSContext; argc: uintN; var vp: jsargRec): Boolean; cdecl;
begin
Result := HasInstance(cx, argc, vp, JSProto_TypedArray);
end;
function SyNodeBindingProc_util(const aEngine: TSMEngine; const bindingNamespaceName: SynUnicode): jsval;
var
obj: PJSRootedObject;
cx: PJSContext;
const
props = JSPROP_ENUMERATE or JSPROP_ENUMERATE or JSPROP_PERMANENT;
begin
cx := aEngine.cx;
obj := cx.NewRootedObject(cx.NewObject(nil));
try
obj.ptr.DefineFunction(cx, 'isArrayBuffer', isArrayBuffer, 1, props);
obj.ptr.DefineFunction(cx, 'isDataView', isDataView, 1, props);
obj.ptr.DefineFunction(cx, 'isDate', isDate, 1, props);
obj.ptr.DefineFunction(cx, 'isMap', isMap, 1, props);
obj.ptr.DefineFunction(cx, 'isMapIterator', isMapIterator, 1, props);
obj.ptr.DefineFunction(cx, 'isPromise', isPromise, 1, props);
obj.ptr.DefineFunction(cx, 'isRegExp', isRegExp, 1, props);
obj.ptr.DefineFunction(cx, 'isSet', isArrayBuffer, 1, props);
obj.ptr.DefineFunction(cx, 'isSetIterator', isSetIterator, 1, props);
obj.ptr.DefineFunction(cx, 'isTypedArray', isTypedArray, 1, props);
// todo
// obj.ptr.DefineFunction(cx, 'getHiddenValue', isArrayBuffer, 1, props);
// obj.ptr.DefineFunction(cx, 'setHiddenValue', isArrayBuffer, 1, props);
// obj.ptr.DefineFunction(cx, 'getProxyDetails', isArrayBuffer, 1, props);
//
// obj.ptr.DefineFunction(cx, 'startSigintWatchdog', isArrayBuffer, 1, props);
// obj.ptr.DefineFunction(cx, 'stopSigintWatchdog', isArrayBuffer, 1, props);
// obj.ptr.DefineFunction(cx, 'watchdogHasPendingSigint', isArrayBuffer, 1, props);
Result := obj.ptr.ToJSValue;
finally
cx.FreeRootedObject(obj);
end;
end;
initialization
TSMEngineManager.RegisterBinding('util', SyNodeBindingProc_util);
end.