Browse Source

* Implement TStream

michael 6 years ago
parent
commit
01edbe957a
1 changed files with 1557 additions and 3 deletions
  1. 1557 3
      packages/rtl/classes.pas

+ 1557 - 3
packages/rtl/classes.pas

@@ -17,7 +17,7 @@ unit Classes;
 interface
 interface
 
 
 uses
 uses
-  RTLConsts, Types, SysUtils;
+  RTLConsts, Types, SysUtils, JS;
 
 
 type
 type
   TNotifyEvent = procedure(Sender: TObject) of object;
   TNotifyEvent = procedure(Sender: TObject) of object;
@@ -606,13 +606,231 @@ type
   end;
   end;
   TComponentClass = Class of TComponent;
   TComponentClass = Class of TComponent;
 
 
+  TSeekOrigin = (soBeginning, soCurrent, soEnd);
+
+  { TStream }
+
+  TStream = class(TObject)
+  private
+    FEndian: TEndian;
+    function MakeInt(B: TBytes; aSize: Integer; Signed: Boolean): NativeInt;
+    function MakeBytes(B: NativeInt; aSize: Integer; Signed: Boolean): TBytes;
+  protected
+    procedure InvalidSeek; virtual;
+    procedure Discard(const Count: NativeInt);
+    procedure DiscardLarge(Count: NativeInt; const MaxBufferSize: Longint);
+    procedure FakeSeekForward(Offset: NativeInt; const Origin: TSeekOrigin; const Pos: NativeInt);
+    function  GetPosition: NativeInt; virtual;
+    procedure SetPosition(const Pos: NativeInt); virtual;
+    function  GetSize: NativeInt; virtual;
+    procedure SetSize(const NewSize: NativeInt); virtual;
+    procedure SetSize64(const NewSize: NativeInt); virtual;
+    procedure ReadNotImplemented;
+    procedure WriteNotImplemented;
+    function ReadMaxSizeData(Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
+    Procedure ReadExactSizeData(Buffer : TBytes; aSize,aCount : NativeInt);
+    function WriteMaxSizeData(Const Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
+    Procedure WriteExactSizeData(Const Buffer : TBytes; aSize,aCount : NativeInt);
+  public
+    function Read(var Buffer: TBytes; Count: Longint): Longint; overload;
+    function Read(Buffer : TBytes; aOffset, Count: Longint): Longint; virtual; abstract; overload;
+
+    function Write(const Buffer: TBytes; Count: Longint): Longint; virtual; overload;
+    function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; virtual; abstract; overload;
+
+    function Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt; virtual; abstract; overload;
+
+    function ReadData(Buffer: TBytes; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: Boolean): NativeInt; overload;
+    function ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: WideChar): NativeInt; overload;
+    function ReadData(var Buffer: WideChar; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: Int8): NativeInt; overload;
+    function ReadData(var Buffer: Int8; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: UInt8): NativeInt; overload;
+    function ReadData(var Buffer: UInt8; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: Int16): NativeInt; overload;
+    function ReadData(var Buffer: Int16; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: UInt16): NativeInt; overload;
+    function ReadData(var Buffer: UInt16; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: Int32): NativeInt; overload;
+    function ReadData(var Buffer: Int32; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: UInt32): NativeInt; overload;
+    function ReadData(var Buffer: UInt32; Count: NativeInt): NativeInt; overload;
+    // NativeLargeint. Stored as a float64, Read as float64.
+    function ReadData(var Buffer: NativeLargeInt): NativeInt; overload;
+    function ReadData(var Buffer: NativeLargeInt; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: NativeLargeUInt): NativeInt; overload;
+    function ReadData(var Buffer: NativeLargeUInt; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: Double): NativeInt; overload;
+    function ReadData(var Buffer: Double; Count: NativeInt): NativeInt; overload;
+    procedure ReadBuffer(var Buffer: TBytes; Count: NativeInt); overload;
+    procedure ReadBuffer(var Buffer: TBytes; Offset, Count: NativeInt); overload;
+
+    procedure ReadBufferData(var Buffer: Boolean); overload;
+    procedure ReadBufferData(var Buffer: Boolean; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: WideChar); overload;
+    procedure ReadBufferData(var Buffer: WideChar; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: Int8); overload;
+    procedure ReadBufferData(var Buffer: Int8; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: UInt8); overload;
+    procedure ReadBufferData(var Buffer: UInt8; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: Int16); overload;
+    procedure ReadBufferData(var Buffer: Int16; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: UInt16); overload;
+    procedure ReadBufferData(var Buffer: UInt16; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: Int32); overload;
+    procedure ReadBufferData(var Buffer: Int32; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: UInt32); overload;
+    procedure ReadBufferData(var Buffer: UInt32; Count: NativeInt); overload;
+    // NativeLargeint. Stored as a float64, Read as float64.
+    procedure ReadBufferData(var Buffer: NativeLargeInt); overload;
+    procedure ReadBufferData(var Buffer: NativeLargeInt; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: NativeLargeUInt); overload;
+    procedure ReadBufferData(var Buffer: NativeLargeUInt; Count: NativeInt); overload;
+    procedure ReadBufferData(var Buffer: Double); overload;
+    procedure ReadBufferData(var Buffer: Double; Count: NativeInt); overload;
+    procedure WriteBuffer(const Buffer: TBytes; Count: NativeInt); overload;
+    procedure WriteBuffer(const Buffer: TBytes; Offset, Count: NativeInt); overload;
+
+    function WriteData(const Buffer: TBytes; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: Boolean): NativeInt; overload;
+    function WriteData(const Buffer: Boolean; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: WideChar): NativeInt; overload;
+    function WriteData(const Buffer: WideChar; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: Int8): NativeInt; overload;
+    function WriteData(const Buffer: Int8; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: UInt8): NativeInt; overload;
+    function WriteData(const Buffer: UInt8; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: Int16): NativeInt; overload;
+    function WriteData(const Buffer: Int16; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: UInt16): NativeInt; overload;
+    function WriteData(const Buffer: UInt16; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: Int32): NativeInt; overload;
+    function WriteData(const Buffer: Int32; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: UInt32): NativeInt; overload;
+    function WriteData(const Buffer: UInt32; Count: NativeInt): NativeInt; overload;
+    // NativeLargeint. Stored as a float64, Read as float64.
+    function WriteData(const Buffer: NativeLargeInt): NativeInt; overload;
+    function WriteData(const Buffer: NativeLargeInt; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: NativeLargeUInt): NativeInt; overload;
+    function WriteData(const Buffer: NativeLargeUInt; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: Double): NativeInt; overload;
+    function WriteData(const Buffer: Double; Count: NativeInt): NativeInt; overload;
+{$IFDEF FPC_HAS_TYPE_EXTENDED}
+    function WriteData(const Buffer: Extended): NativeInt; overload;
+    function WriteData(const Buffer: Extended; Count: NativeInt): NativeInt; overload;
+    function WriteData(const Buffer: TExtended80Rec): NativeInt; overload;
+    function WriteData(const Buffer: TExtended80Rec; Count: NativeInt): NativeInt; overload;
+{$ENDIF}
+    procedure WriteBufferData(Buffer: Int32); overload;
+    procedure WriteBufferData(Buffer: Int32; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: Boolean); overload;
+    procedure WriteBufferData(Buffer: Boolean; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: WideChar); overload;
+    procedure WriteBufferData(Buffer: WideChar; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: Int8); overload;
+    procedure WriteBufferData(Buffer: Int8; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: UInt8); overload;
+    procedure WriteBufferData(Buffer: UInt8; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: Int16); overload;
+    procedure WriteBufferData(Buffer: Int16; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: UInt16); overload;
+    procedure WriteBufferData(Buffer: UInt16; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: UInt32); overload;
+    procedure WriteBufferData(Buffer: UInt32; Count: NativeInt); overload;
+    // NativeLargeint. Stored as a float64, Read as float64.
+    procedure WriteBufferData(Buffer: NativeLargeInt); overload;
+    procedure WriteBufferData(Buffer: NativeLargeInt; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: NativeLargeUInt); overload;
+    procedure WriteBufferData(Buffer: NativeLargeUInt; Count: NativeInt); overload;
+    procedure WriteBufferData(Buffer: Double); overload;
+    procedure WriteBufferData(Buffer: Double; Count: NativeInt); overload;
+    function CopyFrom(Source: TStream; Count: NativeInt): NativeInt;
+{    function ReadComponent(Instance: TComponent): TComponent;
+    function ReadComponentRes(Instance: TComponent): TComponent;
+    procedure WriteComponent(Instance: TComponent);
+    procedure WriteComponentRes(const ResName: string; Instance: TComponent);
+    procedure WriteDescendent(Instance, Ancestor: TComponent);
+    procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
+    procedure WriteResourceHeader(const ResName: string; {!!!:out} var FixupInfo: Longint);
+    procedure FixupResourceHeader(FixupInfo: Longint);
+    procedure ReadResHeader; }
+    function ReadByte : Byte;
+    function ReadWord : Word;
+    function ReadDWord : Cardinal;
+    function ReadQWord : NativeLargeUInt;
+    procedure WriteByte(b : Byte);
+    procedure WriteWord(w : Word);
+    procedure WriteDWord(d : Cardinal);
+    procedure WriteQWord(q : NativeLargeUInt);
+    property Position: NativeInt read GetPosition write SetPosition;
+    property Size: NativeInt read GetSize write SetSize64;
+    Property Endian: TEndian Read FEndian Write FEndian;
+  end;
+
+  { TCustomMemoryStream abstract class }
+
+    TCustomMemoryStream = class(TStream)
+    private
+      FMemory: TJSArrayBuffer;
+      FDataView : TJSDataView;
+      FDataArray : TJSUint8Array;
+      FSize, FPosition: PtrInt;
+      FSizeBoundsSeek : Boolean;
+      function GetDataArray: TJSUint8Array;
+      function GetDataView: TJSDataview;
+    protected
+      Function GetSize : NativeInt; Override;
+      function GetPosition: NativeInt; Override;
+      procedure SetPointer(Ptr: TJSArrayBuffer; ASize: PtrInt);
+      Property DataView : TJSDataview Read GetDataView;
+      Property DataArray : TJSUint8Array Read GetDataArray;
+    public
+      Class Function MemoryToBytes(Mem : TJSArrayBuffer) : TBytes; overload;
+      Class Function MemoryToBytes(Mem : TJSUint8Array) : TBytes; overload;
+      Class Function BytesToMemory(aBytes : TBytes) : TJSArrayBuffer;
+      function Read(Buffer : TBytes; Offset, Count: LongInt): LongInt; override;
+      function Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt; override;
+      procedure SaveToStream(Stream: TStream);
+      property Memory: TJSArrayBuffer read FMemory;
+      Property SizeBoundsSeek : Boolean Read FSizeBoundsSeek Write FSizeBoundsSeek;
+    end;
+
+  { TMemoryStream }
+
+    TMemoryStream = class(TCustomMemoryStream)
+    private
+      FCapacity: PtrInt;
+      procedure SetCapacity(NewCapacity: PtrInt);
+    protected
+      function Realloc(var NewCapacity: PtrInt): TJSArrayBuffer; virtual;
+      property Capacity: PtrInt read FCapacity write SetCapacity;
+    public
+      destructor Destroy; override;
+      procedure Clear;
+      procedure LoadFromStream(Stream: TStream);
+      procedure SetSize(const NewSize: NativeInt); override;
+      function Write(const Buffer: TBytes; Offset, Count: LongInt): LongInt; override;
+    end;
+
+  { TBytesStream }
+
+    TBytesStream = class(TMemoryStream)
+    private
+      function GetBytes: TBytes;
+    public
+      constructor Create(const ABytes: TBytes); virtual; overload;
+      property Bytes: TBytes read GetBytes;
+    end;
+
+
+
 Procedure RegisterClass(AClass : TPersistentClass);
 Procedure RegisterClass(AClass : TPersistentClass);
 Function GetClass(AClassName : string) : TPersistentClass;
 Function GetClass(AClassName : string) : TPersistentClass;
 
 
 implementation
 implementation
 
 
-uses JS;
-
 { TInterfacedPersistent }
 { TInterfacedPersistent }
 
 
 function TInterfacedPersistent._AddRef: Integer;
 function TInterfacedPersistent._AddRef: Integer;
@@ -3722,6 +3940,1342 @@ begin
   Result:=TComponentEnumerator.Create(Self);
   Result:=TComponentEnumerator.Create(Self);
 end;
 end;
 
 
+{ ---------------------------------------------------------------------
+  TStream
+  ---------------------------------------------------------------------}
+
+Resourcestring
+  SStreamInvalidSeek = 'Seek is not implemented for class %s';
+  SStreamNoReading = 'Stream reading is not implemented for class %s';
+  SStreamNoWriting = 'Stream writing is not implemented for class %s';
+  SReadError = 'Could not read data from stream';
+  SWriteError = 'Could not write data to stream';
+  SMemoryStreamError = 'Could not allocate memory';
+  SerrInvalidStreamSize = 'Invalid Stream size';
+
+procedure TStream.ReadNotImplemented;
+begin
+  raise EStreamError.CreateFmt(SStreamNoReading, [ClassName]);
+end;
+
+procedure TStream.WriteNotImplemented;
+begin
+  raise EStreamError.CreateFmt(SStreamNoWriting, [ClassName]);
+end;
+
+function TStream.Read(var Buffer: TBytes; Count: Longint): Longint;
+begin
+  Result:=Read(Buffer,0,Count);
+end;
+
+
+
+function TStream.Write(const Buffer: TBytes; Count: Longint): Longint;
+begin
+  Result:=Self.Write(Buffer,0,Count);
+end;
+
+
+
+function TStream.GetPosition: NativeInt;
+
+begin
+   Result:=Seek(0,soCurrent);
+end;
+
+procedure TStream.SetPosition(const Pos: NativeInt);
+
+begin
+   Seek(pos,soBeginning);
+end;
+
+procedure TStream.SetSize64(const NewSize: NativeInt);
+
+begin
+  // Required because can't use overloaded functions in properties
+  SetSize(NewSize);
+end;
+
+function TStream.GetSize: NativeInt;
+
+var
+   p : NativeInt;
+
+begin
+   p:=Seek(0,soCurrent);
+   GetSize:=Seek(0,soEnd);
+   Seek(p,soBeginning);
+end;
+
+procedure TStream.SetSize(const NewSize: NativeInt);
+
+begin
+  if NewSize<0 then
+    Raise EStreamError.Create(SerrInvalidStreamSize);
+end;
+
+procedure TStream.Discard(const Count: NativeInt);
+
+const
+  CSmallSize      =255;
+  CLargeMaxBuffer =32*1024; // 32 KiB
+
+var
+  Buffer: TBytes;
+
+begin
+  if Count=0 then
+    Exit;
+  if (Count<=CSmallSize) then
+    begin
+    SetLength(Buffer,CSmallSize);
+    ReadBuffer(Buffer,Count)
+    end
+  else
+    DiscardLarge(Count,CLargeMaxBuffer);
+end;
+
+procedure TStream.DiscardLarge(Count: NativeInt; const MaxBufferSize: Longint);
+
+var
+  Buffer: TBytes;
+
+begin
+  if Count=0 then
+     Exit;
+  if Count>MaxBufferSize then
+    SetLength(Buffer,MaxBufferSize)
+  else
+    SetLength(Buffer,Count);
+  while (Count>=Length(Buffer)) do
+    begin
+    ReadBuffer(Buffer,Length(Buffer));
+    Dec(Count,Length(Buffer));
+    end;
+  if Count>0 then
+    ReadBuffer(Buffer,Count);
+end;
+
+procedure TStream.InvalidSeek;
+
+begin
+  raise EStreamError.CreateFmt(SStreamInvalidSeek, [ClassName]);
+end;
+
+procedure TStream.FakeSeekForward(Offset: NativeInt;  const Origin: TSeekOrigin; const Pos: NativeInt);
+
+begin
+  if Origin=soBeginning then
+     Dec(Offset,Pos);
+  if (Offset<0) or (Origin=soEnd) then
+    InvalidSeek;
+  if Offset>0 then
+    Discard(Offset);
+ end;
+
+function TStream.ReadData({var} Buffer: TBytes; Count: NativeInt): NativeInt;
+begin
+ Result:=Read(Buffer,0,Count);
+end;
+
+
+function TStream.ReadMaxSizeData(Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
+
+Var
+  CP : NativeInt;
+
+begin
+  if aCount<=aSize then
+    Result:=read(Buffer,aCount)
+  else
+    begin
+    Result:=Read(Buffer,aSize);
+    CP:=Position;
+    Result:=Result+Seek(aCount-aSize,soCurrent)-CP;
+    end
+end;
+
+function TStream.WriteMaxSizeData(const Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
+Var
+  CP : NativeInt;
+
+begin
+  if aCount<=aSize then
+    Result:=Self.Write(Buffer,aCount)
+  else
+    begin
+    Result:=Self.Write(Buffer,aSize);
+    CP:=Position;
+    Result:=Result+Seek(aCount-aSize,soCurrent)-CP;
+    end
+end;
+
+procedure TStream.WriteExactSizeData(const Buffer : TBytes; aSize, aCount: NativeInt);
+begin
+  // Embarcadero docs mentions no exception. Does not seem very logical
+  WriteMaxSizeData(Buffer,aSize,ACount);
+end;
+
+procedure TStream.ReadExactSizeData(Buffer : TBytes; aSize, aCount: NativeInt);
+begin
+  if ReadMaxSizeData(Buffer,aSize,ACount)<>aCount then
+     Raise EReadError.Create(SReadError);
+end;
+
+
+function TStream.ReadData(var Buffer: Boolean): NativeInt;
+
+Var
+  B : Byte;
+
+begin
+  Result:=ReadData(B,1);
+  if Result=1 then
+    Buffer:=B<>0;
+end;
+
+function TStream.ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt;
+
+Var
+  B : TBytes;
+
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,1,Count);
+  if Result>0 then
+    Buffer:=B[0]<>0
+end;
+
+
+function TStream.ReadData(var Buffer: WideChar): NativeInt;
+begin
+  Result:=ReadData(Buffer,2);
+end;
+
+function TStream.ReadData(var Buffer: WideChar; Count: NativeInt): NativeInt;
+
+Var
+  W : Word;
+
+begin
+  Result:=ReadData(W,Count);
+  if Result=2 then
+    Buffer:=WideChar(W);
+end;
+
+function TStream.ReadData(var Buffer: Int8): NativeInt;
+begin
+  Result:=ReadData(Buffer,1);
+end;
+
+Function TStream.MakeInt(B : TBytes; aSize : Integer; Signed : Boolean) : NativeInt;
+
+Var
+  Mem : TJSArrayBuffer;
+  A : TJSUInt8Array;
+  D : TJSDataView;
+  isLittle : Boolean;
+
+begin
+  IsLittle:=(Endian=TEndian.Little);
+  Mem:=TJSArrayBuffer.New(Length(B));
+  A:=TJSUInt8Array.new(Mem);
+  A._set(B);
+  D:=TJSDataView.New(Mem);
+  if Signed then
+    case aSize of
+      1 : Result:=D.getInt8(0);
+      2 : Result:=D.getInt16(0,IsLittle);
+      4 : Result:=D.getInt32(0,IsLittle);
+      // Todo : fix sign
+      8 : Result:=Round(D.getFloat64(0,IsLittle));
+    end
+  else
+    case aSize of
+      1 : Result:=D.getUInt8(0);
+      2 : Result:=D.getUInt16(0,IsLittle);
+      4 : Result:=D.getUInt32(0,IsLittle);
+      8 : Result:=Round(D.getFloat64(0,IsLittle));
+    end
+end;
+
+function TStream.MakeBytes(B: NativeInt; aSize: Integer; Signed: Boolean): TBytes;
+
+
+Var
+  Mem : TJSArrayBuffer;
+  A : TJSUInt8Array;
+  D : TJSDataView;
+  isLittle : Boolean;
+
+begin
+  IsLittle:=(Endian=TEndian.Little);
+  Mem:=TJSArrayBuffer.New(aSize);
+  D:=TJSDataView.New(Mem);
+  if Signed then
+    case aSize of
+      1 : D.setInt8(0,B);
+      2 : D.setInt16(0,B,IsLittle);
+      4 : D.setInt32(0,B,IsLittle);
+      8 : D.setFloat64(0,B,IsLittle);
+    end
+  else
+    case aSize of
+      1 : D.SetUInt8(0,B);
+      2 : D.SetUInt16(0,B,IsLittle);
+      4 : D.SetUInt32(0,B,IsLittle);
+      8 : D.setFloat64(0,B,IsLittle);
+    end;
+  SetLength(Result,aSize);
+  A:=TJSUInt8Array.new(Mem);
+  Result:=TMemoryStream.MemoryToBytes(A);
+end;
+
+
+function TStream.ReadData(var Buffer: Int8; Count: NativeInt): NativeInt;
+
+Var
+  B : TBytes;
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,1,Count);
+  if Result>=1 then
+    Buffer:=MakeInt(B,1,True);
+end;
+
+function TStream.ReadData(var Buffer: UInt8): NativeInt;
+begin
+  Result:=ReadData(Buffer,1);
+end;
+
+function TStream.ReadData(var Buffer: UInt8; Count: NativeInt): NativeInt;
+Var
+  B : TBytes;
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,1,Count);
+  if Result>=1 then
+    Buffer:=MakeInt(B,1,False);
+end;
+
+function TStream.ReadData(var Buffer: Int16): NativeInt;
+begin
+  Result:=ReadData(Buffer,2);
+end;
+
+function TStream.ReadData(var Buffer: Int16; Count: NativeInt): NativeInt;
+Var
+  B : TBytes;
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,2,Count);
+  if Result>=2 then
+    Buffer:=MakeInt(B,2,True);
+end;
+
+function TStream.ReadData(var Buffer: UInt16): NativeInt;
+begin
+  Result:=ReadData(Buffer,2);
+end;
+
+function TStream.ReadData(var Buffer: UInt16; Count: NativeInt): NativeInt;
+Var
+  B : TBytes;
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,2,Count);
+  if Result>=2 then
+    Buffer:=MakeInt(B,2,False);
+end;
+
+function TStream.ReadData(var Buffer: Int32): NativeInt;
+begin
+  Result:=ReadData(Buffer,4);
+end;
+
+function TStream.ReadData(var Buffer: Int32; Count: NativeInt): NativeInt;
+Var
+  B : TBytes;
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,4,Count);
+  if Result>=4 then
+    Buffer:=MakeInt(B,4,True);
+end;
+
+function TStream.ReadData(var Buffer: UInt32): NativeInt;
+begin
+  Result:=ReadData(Buffer,4);
+end;
+
+function TStream.ReadData(var Buffer: UInt32; Count: NativeInt): NativeInt;
+
+Var
+  B : TBytes;
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,4,Count);
+  if Result>=4 then
+    Buffer:=MakeInt(B,4,False);
+end;
+
+
+function TStream.ReadData(var Buffer: NativeInt): NativeInt;
+
+begin
+  Result:=ReadData(Buffer,8);
+end;
+
+function TStream.ReadData(var Buffer: NativeInt; Count: NativeInt): NativeInt;
+
+Var
+  B : TBytes;
+
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,8,8);
+  if Result>=8 then
+    Buffer:=MakeInt(B,8,True);
+end;
+
+function TStream.ReadData(var Buffer: NativeLargeUInt): NativeInt;
+begin
+  Result:=ReadData(Buffer,8);
+end;
+
+function TStream.ReadData(var Buffer: NativeLargeUInt; Count: NativeInt): NativeInt;
+
+Var
+  B : TBytes;
+  B1 : Integer;
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,4,4);
+  if Result>=4 then
+    begin
+    B1:=MakeInt(B,4,False);
+    Result:=Result+ReadMaxSizeData(B,4,4);
+    Buffer:=MakeInt(B,4,False);
+    Buffer:=(Buffer shl 32) or B1;
+    end;
+end;
+
+function TStream.ReadData(var Buffer: Double): NativeInt;
+begin
+  Result:=ReadData(Buffer,8);
+end;
+
+function TStream.ReadData(var Buffer: Double; Count: NativeInt): NativeInt;
+
+Var
+  B : TBytes;
+  Mem : TJSArrayBuffer;
+  A : TJSUInt8Array;
+  D : TJSDataView;
+
+begin
+  SetLength(B,Count);
+  Result:=ReadMaxSizeData(B,8,Count);
+  if Result>=8 then
+    begin
+    Mem:=TJSArrayBuffer.New(8);
+    A:=TJSUInt8Array.new(Mem);
+    A._set(B);
+    D:=TJSDataView.New(Mem);
+    Buffer:=D.getFloat64(0);
+    end;
+end;
+
+procedure TStream.ReadBuffer(var Buffer: TBytes; Count: NativeInt);
+begin
+  ReadBuffer(Buffer,0,Count);
+end;
+
+procedure TStream.ReadBuffer(var Buffer: TBytes; Offset, Count: NativeInt);
+begin
+  if Read(Buffer,OffSet,Count)<>Count then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Boolean);
+begin
+  ReadBufferData(Buffer,1);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Boolean; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: WideChar);
+begin
+  ReadBufferData(Buffer,2);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: WideChar; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Int8);
+begin
+  ReadBufferData(Buffer,1);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Int8; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: UInt8);
+begin
+  ReadBufferData(Buffer,1);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: UInt8; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Int16);
+begin
+  ReadBufferData(Buffer,2);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Int16; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: UInt16);
+begin
+  ReadBufferData(Buffer,2);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: UInt16; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Int32);
+begin
+  ReadBufferData(Buffer,4);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Int32; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: UInt32);
+begin
+  ReadBufferData(Buffer,4);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: UInt32; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: NativeLargeInt);
+begin
+  ReadBufferData(Buffer,8)
+end;
+
+procedure TStream.ReadBufferData(var Buffer: NativeLargeInt; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: NativeLargeUInt);
+begin
+  ReadBufferData(Buffer,8);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: NativeLargeUInt; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+
+procedure TStream.ReadBufferData(var Buffer: Double);
+begin
+  ReadBufferData(Buffer,8);
+end;
+
+procedure TStream.ReadBufferData(var Buffer: Double; Count: NativeInt);
+begin
+  if (ReadData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SReadError);
+end;
+
+procedure TStream.WriteBuffer(const Buffer: TBytes; Count: NativeInt);
+begin
+  WriteBuffer(Buffer,0,Count);
+end;
+
+procedure TStream.WriteBuffer(const Buffer: TBytes; Offset, Count: NativeInt);
+begin
+  if Self.Write(Buffer,Offset,Count)<>Count then
+     Raise EStreamError.Create(SWriteError);
+end;
+
+function TStream.WriteData(const Buffer: TBytes; Count: NativeInt): NativeInt;
+begin
+  Result:=Self.Write(Buffer, 0, Count);
+end;
+
+function TStream.WriteData(const Buffer: Boolean): NativeInt;
+begin
+  Result:=WriteData(Buffer,1);
+end;
+
+function TStream.WriteData(const Buffer: Boolean; Count: NativeInt): NativeInt;
+
+Var
+  B : Int8;
+
+begin
+  B:=Ord(Buffer);
+  Result:=WriteData(B,Count);
+end;
+
+function TStream.WriteData(const Buffer: WideChar): NativeInt;
+
+begin
+  Result:=WriteData(Buffer,2);
+end;
+
+function TStream.WriteData(const Buffer: WideChar; Count: NativeInt): NativeInt;
+Var
+  U : UInt16;
+begin
+  U:=Ord(Buffer);
+  Result:=WriteData(U,Count);
+end;
+
+function TStream.WriteData(const Buffer: Int8): NativeInt;
+
+begin
+  Result:=WriteData(Buffer,1);
+end;
+
+function TStream.WriteData(const Buffer: Int8; Count: NativeInt): NativeInt;
+begin
+  Result:=WriteMaxSizeData(MakeBytes(Buffer,1,True),1,Count);
+end;
+
+function TStream.WriteData(const Buffer: UInt8): NativeInt;
+begin
+  Result:=WriteData(Buffer,1);
+end;
+
+function TStream.WriteData(const Buffer: UInt8; Count: NativeInt): NativeInt;
+begin
+  Result:=WriteMaxSizeData(MakeBytes(Buffer,1,False),1,Count);
+end;
+
+function TStream.WriteData(const Buffer: Int16): NativeInt;
+begin
+  Result:=WriteData(Buffer,2);
+end;
+
+function TStream.WriteData(const Buffer: Int16; Count: NativeInt): NativeInt;
+begin
+  Result:=WriteMaxSizeData(MakeBytes(Buffer,2,True),2,Count);
+end;
+
+function TStream.WriteData(const Buffer: UInt16): NativeInt;
+begin
+  Result:=WriteData(Buffer,2);
+end;
+
+function TStream.WriteData(const Buffer: UInt16; Count: NativeInt): NativeInt;
+begin
+  Result:=WriteMaxSizeData(MakeBytes(Buffer,2,True),2,Count);
+end;
+
+function TStream.WriteData(const Buffer: Int32): NativeInt;
+begin
+  Result:=WriteData(Buffer,4);
+end;
+
+function TStream.WriteData(const Buffer: Int32; Count: NativeInt): NativeInt;
+begin
+  Result:=WriteMaxSizeData(MakeBytes(Buffer,4,True),4,Count);
+end;
+
+function TStream.WriteData(const Buffer: UInt32): NativeInt;
+begin
+  Result:=WriteData(Buffer,4);
+end;
+
+function TStream.WriteData(const Buffer: UInt32; Count: NativeInt): NativeInt;
+begin
+  Result:=WriteMaxSizeData(MakeBytes(Buffer,4,False),4,Count);
+end;
+
+function TStream.WriteData(const Buffer: NativeLargeInt): NativeInt;
+begin
+  Result:=WriteData(Buffer,8);
+end;
+
+function TStream.WriteData(const Buffer: NativeLargeInt; Count: NativeInt): NativeInt;
+begin
+  Result:=WriteMaxSizeData(MakeBytes(Buffer,8,True),8,Count);
+end;
+
+function TStream.WriteData(const Buffer: NativeLargeUInt): NativeInt;
+begin
+  Result:=WriteData(Buffer,8);
+end;
+
+function TStream.WriteData(const Buffer: NativeLargeUInt; Count: NativeInt): NativeInt;
+begin
+  Result:=WriteMaxSizeData(MakeBytes(Buffer,8,False),8,Count);
+end;
+
+function TStream.WriteData(const Buffer: Double): NativeInt;
+begin
+  Result:=WriteData(Buffer,8);
+end;
+
+function TStream.WriteData(const Buffer: Double; Count: NativeInt): NativeInt;
+
+Var
+  Mem : TJSArrayBuffer;
+  A : TJSUint8array;
+  D : TJSDataview;
+  B : TBytes;
+  I : Integer;
+
+begin
+  Mem:=TJSArrayBuffer.New(8);
+  D:=TJSDataView.new(Mem);
+  D.setFloat64(0,Buffer);
+  SetLength(B,8);
+  A:=TJSUint8array.New(Mem);
+  For I:=0 to 7 do
+    B[i]:=A[i];
+  Result:=WriteMaxSizeData(B,8,Count);
+end;
+
+
+procedure TStream.WriteBufferData(Buffer: Int32);
+begin
+  WriteBufferData(Buffer,4);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Int32; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Boolean);
+begin
+  WriteBufferData(Buffer,1);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Boolean; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: WideChar);
+begin
+  WriteBufferData(Buffer,2);
+end;
+
+procedure TStream.WriteBufferData(Buffer: WideChar; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Int8);
+begin
+  WriteBufferData(Buffer,1);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Int8; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: UInt8);
+begin
+  WriteBufferData(Buffer,1);
+end;
+
+procedure TStream.WriteBufferData(Buffer: UInt8; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Int16);
+begin
+  WriteBufferData(Buffer,2);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Int16; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: UInt16);
+begin
+  WriteBufferData(Buffer,2);
+end;
+
+procedure TStream.WriteBufferData(Buffer: UInt16; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: UInt32);
+begin
+  WriteBufferData(Buffer,4);
+end;
+
+procedure TStream.WriteBufferData(Buffer: UInt32; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: NativeInt);
+begin
+  WriteBufferData(Buffer,8);
+end;
+
+procedure TStream.WriteBufferData(Buffer: NativeInt; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: NativeLargeUInt);
+begin
+  WriteBufferData(Buffer,8);
+end;
+
+procedure TStream.WriteBufferData(Buffer: NativeLargeUInt; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Double);
+begin
+  WriteBufferData(Buffer,8);
+end;
+
+procedure TStream.WriteBufferData(Buffer: Double; Count: NativeInt);
+begin
+  if (WriteData(Buffer,Count)<>Count) then
+    Raise EStreamError.Create(SWriteError);
+end;
+
+
+
+function TStream.CopyFrom(Source: TStream; Count: NativeInt): NativeInt;
+
+var
+   Buffer: TBytes;
+   BufferSize, i: LongInt;
+
+const
+   MaxSize = $20000;
+begin
+   Result:=0;
+   if Count=0 then
+     Source.Position:=0;   // This WILL fail for non-seekable streams...
+   BufferSize:=MaxSize;
+   if (Count>0) and (Count<BufferSize) then
+     BufferSize:=Count;    // do not allocate more than needed
+   SetLength(Buffer,BufferSize);
+   if Count=0 then
+     repeat
+       i:=Source.Read(Buffer,BufferSize);
+       if i>0 then
+         WriteBuffer(Buffer,i);
+       Inc(Result,i);
+     until i<BufferSize
+   else
+     while Count>0 do
+       begin
+       if Count>BufferSize then
+         i:=BufferSize
+       else
+         i:=Count;
+       Source.ReadBuffer(Buffer,i);
+       WriteBuffer(Buffer,i);
+       Dec(count,i);
+       Inc(Result,i);
+       end;
+end;
+
+(*
+function TStream.ReadComponent(Instance: TComponent): TComponent;
+
+  var
+    Reader: TReader;
+
+  begin
+
+    Reader := TReader.Create(Self, 4096);
+    try
+      Result := Reader.ReadRootComponent(Instance);
+    finally
+      Reader.Free;
+    end;
+
+  end;
+
+function TStream.ReadComponentRes(Instance: TComponent): TComponent;
+
+  begin
+
+    ReadResHeader;
+    Result := ReadComponent(Instance);
+
+  end;
+
+procedure TStream.WriteComponent(Instance: TComponent);
+
+  begin
+
+    WriteDescendent(Instance, nil);
+
+  end;
+
+procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
+
+  begin
+
+    WriteDescendentRes(ResName, Instance, nil);
+
+  end;
+
+procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
+
+  var
+     Driver : TAbstractObjectWriter;
+     Writer : TWriter;
+
+  begin
+
+     Driver := TBinaryObjectWriter.Create(Self, 4096);
+     Try
+       Writer := TWriter.Create(Driver);
+       Try
+         Writer.WriteDescendent(Instance, Ancestor);
+       Finally
+         Writer.Destroy;
+       end;
+     Finally
+       Driver.Free;
+     end;
+
+  end;
+
+procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
+
+  var
+    FixupInfo: Longint;
+
+  begin
+
+    { Write a resource header }
+    WriteResourceHeader(ResName, FixupInfo);
+    { Write the instance itself }
+    WriteDescendent(Instance, Ancestor);
+    { Insert the correct resource size into the resource header }
+    FixupResourceHeader(FixupInfo);
+
+  end;
+
+
+procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Longint);
+  var
+    ResType, Flags : word;
+  begin
+     ResType:=NtoLE(word($000A));
+     Flags:=NtoLE(word($1030));
+     { Note: This is a Windows 16 bit resource }
+     { Numeric resource type }
+     WriteByte($ff);
+     { Application defined data }
+     WriteWord(ResType);
+     { write the name as asciiz }
+     WriteBuffer(ResName[1],length(ResName));
+     WriteByte(0);
+     { Movable, Pure and Discardable }
+     WriteWord(Flags);
+     { Placeholder for the resource size }
+     WriteDWord(0);
+     { Return current stream position so that the resource size can be
+       inserted later }
+     FixupInfo := Position;
+  end;
+
+procedure TStream.FixupResourceHeader(FixupInfo: Longint);
+
+  var
+     ResSize,TmpResSize : Longint;
+
+  begin
+
+    ResSize := Position - FixupInfo;
+    TmpResSize := NtoLE(longword(ResSize));
+
+    { Insert the correct resource size into the placeholder written by
+      WriteResourceHeader }
+    Position := FixupInfo - 4;
+    WriteDWord(TmpResSize);
+    { Seek back to the end of the resource }
+    Position := FixupInfo + ResSize;
+
+  end;
+
+procedure TStream.ReadResHeader;
+  var
+    ResType, Flags : word;
+  begin
+     try
+       { Note: This is a Windows 16 bit resource }
+       { application specific resource ? }
+       if ReadByte<>$ff then
+         raise EInvalidImage.Create(SInvalidImage);
+       ResType:=LEtoN(ReadWord);
+       if ResType<>$000a then
+         raise EInvalidImage.Create(SInvalidImage);
+       { read name }
+       while ReadByte<>0 do
+         ;
+       { check the access specifier }
+       Flags:=LEtoN(ReadWord);
+       if Flags<>$1030 then
+         raise EInvalidImage.Create(SInvalidImage);
+       { ignore the size }
+       ReadDWord;
+     except
+       on EInvalidImage do
+         raise;
+       else
+         raise EInvalidImage.create(SInvalidImage);
+     end;
+  end;
+*)
+
+function TStream.ReadByte : Byte;
+
+begin
+  ReadBufferData(Result,1);
+end;
+
+function TStream.ReadWord : Word;
+
+begin
+  ReadBufferData(Result,2);
+end;
+
+function TStream.ReadDWord : Cardinal;
+
+begin
+  ReadBufferData(Result,4);
+end;
+
+function TStream.ReadQWord: NativeLargeUInt;
+
+begin
+  ReadBufferData(Result,8);
+end;
+
+
+procedure TStream.WriteByte(b : Byte);
+
+begin
+  WriteBufferData(b,1);
+end;
+
+procedure TStream.WriteWord(w : Word);
+
+begin
+  WriteBufferData(W,2);
+end;
+
+procedure TStream.WriteDWord(d : Cardinal);
+
+begin
+  WriteBufferData(d,4);
+end;
+
+procedure TStream.WriteQWord(q: NativeLargeUInt);
+begin
+  WriteBufferData(q,8);
+end;
+
+{****************************************************************************}
+{*                             TCustomMemoryStream                          *}
+{****************************************************************************}
+
+procedure TCustomMemoryStream.SetPointer(Ptr: TJSArrayBuffer; ASize: PtrInt);
+
+begin
+  FMemory:=Ptr;
+  FSize:=ASize;
+  FDataView:=Nil;
+  FDataArray:=Nil;
+end;
+
+
+Class Function TCustomMemoryStream.MemoryToBytes(Mem : TJSArrayBuffer) : TBytes; overload;
+
+begin
+  Result:=MemoryToBytes(TJSUint8Array.New(Mem));
+end;
+
+class function TCustomMemoryStream.MemoryToBytes(Mem: TJSUint8Array): TBytes;
+
+Var
+  I : Integer;
+
+begin
+  // This must be improved, but needs some asm or TJSFunction.call() to implement answers in
+  // https://stackoverflow.com/questions/29676635/convert-uint8array-to-array-in-javascript
+  for i:=0 to mem.length-1 do
+    Result[i]:=Mem[i];
+end;
+
+class function TCustomMemoryStream.BytesToMemory(aBytes: TBytes): TJSArrayBuffer;
+
+Var
+  a : TJSUint8Array;
+
+begin
+  Result:=TJSArrayBuffer.new(Length(aBytes));
+  A:=TJSUint8Array.New(Result);
+  A._set(aBytes);
+end;
+
+function TCustomMemoryStream.GetDataArray: TJSUint8Array;
+begin
+  if FDataArray=Nil then
+    FDataArray:=TJSUint8Array.new(Memory);
+  Result:=FDataArray;
+end;
+
+function TCustomMemoryStream.GetDataView: TJSDataview;
+begin
+  if FDataView=Nil then
+    FDataView:=TJSDataView.New(Memory);
+  Result:=FDataView;
+end;
+
+function TCustomMemoryStream.GetSize: NativeInt;
+
+begin
+  Result:=FSize;
+end;
+
+function TCustomMemoryStream.GetPosition: NativeInt;
+begin
+  Result:=FPosition;
+end;
+
+
+function TCustomMemoryStream.Read(Buffer : TBytes; offset, Count: LongInt): LongInt;
+
+Var
+  I,Src,Dest : Integer;
+
+begin
+  Result:=0;
+  If (FSize>0) and (FPosition<Fsize) and (FPosition>=0) then
+    begin
+    Result:=Count;
+    If (Result>(FSize-FPosition)) then
+      Result:=(FSize-FPosition);
+    Src:=FPosition;
+    Dest:=Offset;
+    I:=0;
+    While I<Result do
+      begin
+      Buffer[Dest]:=DataView.getUint8(Src);
+      inc(Src);
+      inc(Dest);
+      inc(I);
+      end;
+    FPosition:=Fposition+Result;
+    end;
+end;
+
+
+function TCustomMemoryStream.Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt;
+
+begin
+  Case Origin of
+    soBeginning : FPosition:=Offset;
+    soEnd       : FPosition:=FSize+Offset;
+    soCurrent   : FPosition:=FPosition+Offset;
+  end;
+  if SizeBoundsSeek and (FPosition>FSize) then
+    FPosition:=FSize;
+  Result:=FPosition;
+  {$IFDEF DEBUG}
+  if Result < 0 then
+    raise Exception.Create('TCustomMemoryStream');
+  {$ENDIF}
+end;
+
+
+procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
+
+begin
+  if FSize>0 then
+    Stream.WriteBuffer(TMemoryStream.MemoryToBytes(Memory),FSize);
+end;
+
+
+
+{****************************************************************************}
+{*                             TMemoryStream                                *}
+{****************************************************************************}
+
+
+Const TMSGrow = 4096; { Use 4k blocks. }
+
+procedure TMemoryStream.SetCapacity(NewCapacity: PtrInt);
+
+begin
+  SetPointer (Realloc(NewCapacity),Fsize);
+  FCapacity:=NewCapacity;
+end;
+
+
+function TMemoryStream.Realloc(var NewCapacity: PtrInt): TJSArrayBuffer;
+
+Var
+  GC : PtrInt;
+  DestView : TJSUInt8array;
+
+begin
+  If NewCapacity<0 Then
+    NewCapacity:=0
+  else
+    begin
+      GC:=FCapacity + (FCapacity div 4);
+      // if growing, grow at least a quarter
+      if (NewCapacity>FCapacity) and (NewCapacity < GC) then
+        NewCapacity := GC;
+      // round off to block size.
+      NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
+    end;
+  // Only now check !
+  If NewCapacity=FCapacity then
+    Result:=FMemory
+  else if NewCapacity=0 then
+    Result:=Nil
+  else
+    begin
+    // New buffer
+    Result:=TJSArrayBuffer.New(NewCapacity);
+    If (Result=Nil)  then
+      Raise EStreamError.Create(SMemoryStreamError);
+    // Transfer
+    DestView:=TJSUInt8array.New(Result);
+    Destview._Set(Self.DataArray);
+    end;
+end;
+
+
+destructor TMemoryStream.Destroy;
+
+begin
+  Clear;
+  Inherited Destroy;
+end;
+
+
+procedure TMemoryStream.Clear;
+
+begin
+  FSize:=0;
+  FPosition:=0;
+  SetCapacity (0);
+end;
+
+
+procedure TMemoryStream.LoadFromStream(Stream: TStream);
+
+begin
+  Stream.Position:=0;
+  SetSize(Stream.Size);
+  If FSize>0 then Stream.ReadBuffer(MemoryToBytes(FMemory),FSize);
+end;
+
+procedure TMemoryStream.SetSize(const NewSize: NativeInt);
+
+begin
+  SetCapacity (NewSize);
+  FSize:=NewSize;
+  IF FPosition>FSize then
+    FPosition:=FSize;
+end;
+
+function TMemoryStream.Write(Const Buffer : TBytes; OffSet, Count: LongInt): LongInt;
+
+Var NewPos : PtrInt;
+
+begin
+  If (Count=0) or (FPosition<0) then
+    exit(0);
+  NewPos:=FPosition+Count;
+  If NewPos>Fsize then
+    begin
+    IF NewPos>FCapacity then
+      SetCapacity (NewPos);
+    FSize:=Newpos;
+    end;
+  DataArray._set(Copy(Buffer,Offset,Count),FPosition);
+  FPosition:=NewPos;
+  Result:=Count;
+end;
+
+{****************************************************************************}
+{*                              TBytesStream                                *}
+{****************************************************************************}
+
+constructor TBytesStream.Create(const ABytes: TBytes);
+begin
+  inherited Create;
+  SetPointer(TMemoryStream.BytesToMemory(aBytes),Length(ABytes));
+  FCapacity:=Length(ABytes);
+end;
+
+function TBytesStream.GetBytes: TBytes;
+begin
+  Result:=TMemoryStream.MemoryToBytes(Memory);
+end;
+
+
 
 
 { ---------------------------------------------------------------------
 { ---------------------------------------------------------------------
   Global routines
   Global routines