4

我正在尝试将 peerjs 库包装在 Smart Mobile Studio 中。
但是我不确定包装的规则是什么。
我查看了 RTL 单元并试图从中推断出一些规则。

然而,一些问题仍然存在。

(function(exports){
var binaryFeatures = {};
binaryFeatures.useBlobBuilder = (function(){
  ...
})();

Peer.js从看起来像匿名函数的东西开始,只有一个参数(导出)。

以下包装器是否binaryFeatures正确?

type
  JBinaryFeatures = class external 'binaryFeatures'
  public
    function useBlobBuilder: boolean; external 'useBlobBuilder';
    function useArrayBufferView: boolean; external 'useArrayBufferView';
  end;

接下来是一个函数“EventEmitter”,它用作连接类(Peer/DataConnection 等)的原型。

如何告诉 SMS JPeer 继承自 JEventEmitter?

我试过了:

JPeer = class{(TEventEmitter)} external 'Peer'

然而,这是不合法的。

最后,Peer.js 中定义的一些类永远不会分配给变量,而是在某个类中动态实例化。
我是使用external 'Object'这些类的构造,还是根据Peer.js文件命名它们?

JNegotiator = class external 'Negotiator'  
JNegotiator = class external 'Object' 

下面是我尝试编写包装器和需要包装的 Peer.js 文件。

PeerWrapper.pas

unit PeerWrapper;

interface

{$R 'file:peer.js'}

uses 
  SmartCL.System;

type
  JBinaryFeatures = class external 'binaryFeatures'
  public
    function useBlobBuilder: boolean; external 'useBlobBuilder';
    function useArrayBufferView: boolean; external 'useArrayBufferView';
  end;

//  Parent class for the packing functions inside the connections.
//  TBinaryPack = class external 'binaryPack'
//  public
//    function unpack(data: variant): variant; external 'unpack';
//    function pack(data: variant): variant; external 'pack';
//  end;

  JReliable = class;
  JUtil = class;
  JPeer = class;
  JDataConnection = class;
  JMediaConnection = class;

//var
//  FBlobBuilder: variant; external 'BlobBuilder';
//  FBinaryFeatures: TBinaryFeatures; external 'binaryFeatures';
//  //FBinaryPack: TBinaryPack;
//  FReliable: TReliable; external 'reliable';
//  FUtil: TUtil; external 'util';
//  FPeer: TPeer; external 'Peer';
//  FRTCSessionDescription: variant;
//  FRTCPeerConnection: variant;
//  FRTCIceCandidate: variant;

type

//  Parent class for socket type connections.
  JEventEmitter = class external 'eventEmitter'
  public
    constructor Create; external 'EventEmitter';
    function addListener(&type, listener, scope, once: variant): TEventEmitter; external 'addListener';
    function &on(&type, listener, scope, once: variant): TEventEmitter; external 'on';
    function once(&type, listener, scope: variant): TEventEmitter; external 'once';
    function removeListener(&type, listener, scope: variant): TEventEmitter; external 'removeListener';
    function off(&type, listener, scope: variant): TEventEmitter; external 'off';
    function removeAllListeners(&type: variant): TEventEmitter; external 'removeAllListeners';
    function listeners(&type: variant): variant; external 'listeners';
    function emit(&type: variant): boolean; external 'emit';   //vararg function
  end;

  JReliable = class external 'reliable'
  public
    constructor Create(dc, debug: variant); external 'Reliable';
    procedure send(msg: variant); external 'send';
    function higherBandwidthSDP(sdp: string): string; external 'higherBandwidthSDP';
    function onmessage(msg: variant): variant; external 'onmessage';
  end;

  JUtil = class external 'util'
  private
    FCloud_host: string; external 'CLOUD_HOST';
    FCloud_port: string; external 'CLOUD_PORT';
    chunkedBrowsers: variant; external 'chunkedBrowsers';
    chunkedMTU: integer; external 'chunkedMTU';
    FLogLevel: integer; external 'logLevel';
    FDefaultConfig: variant; external 'defaultConfig';
    FDebug: boolean; external 'debug';
  public
    procedure setLogLevel(level: integer); external 'setLogLevel';
    procedure setLogFunction(fn: variant); external 'setLogFunction';
    function browser: string; external 'browser';
    function supports: variant; external 'supports';
    function validateId(id: string): boolean; external 'validateId';
    function validateKey(key: string): boolean; external 'validateKey';
    function unpack(data: variant): variant; external 'unpack';
    function pack(data: variant): variant; external 'pack';
    procedure log; external 'log';
    procedure setZeroTimeout(global: variant); external 'setZeroTimeout';
    function chunk(blob: variant): variant; external 'chunk';
    procedure blobToArrayBuffer(blob: variant; callback: variant); external 'blobToArrayBuffer';
    procedure blobToBinaryString(blob: variant; callback: variant); external 'blobToBinaryString';
    function binaryStringToArrayBuffer(binary: variant): variant; external 'binaryStringToArrayBuffer';
    function randomToken: string; external 'randomToken';
    function isSecure: boolean; external 'isSecure';

    property CloudHost: string read FCloud_host;
    property CloudPort: string read FCloud_port;
    property LogLevel: integer read FLogLevel;
    property DefaultConfig: variant read FDefaultConfig;
    property Debug: boolean read FDebug;
  end;

  JPeer = class{(TEventEmitter)} external 'Peer'
  public
    //inherited from EventEmitter
    function addListener(&type, listener, scope, once: variant): TEventEmitter; external 'addListener';
    function &on(&type, listener, scope, once: variant): TEventEmitter; external 'on';
    function once(&type, listener, scope: variant): TEventEmitter; external 'once';
    function removeListener(&type, listener, scope: variant): TEventEmitter; external 'removeListener';
    function off(&type, listener, scope: variant): TEventEmitter; external 'off';
    function removeAllListeners(&type: variant): TEventEmitter; external 'removeAllListeners';
    function listeners(&type: variant): variant; external 'listeners';
    function emit(&type: variant): boolean; external 'emit';   //vararg function
  public
    constructor Create(id: string; options: variant); external 'Peer';
    function connect(peer: TPeer; options: variant): TDataConnection; external 'connect';
    function call(peer: TPeer; stream: variant; options: variant): TMediaConnection; external 'call';
    function getConnection(peer: TPeer; id: string): TEventEmitter; external 'getConnection';
    procedure emitError(&type: variant; err: variant); external 'emitError';
    procedure destroy; external 'destroy';
    procedure disconnect; external 'disconnect';
    procedure reconnect; external 'reconnect';
    procedure listAllPeers(callback: variant); external 'listAllPeers';
  end;

  JDataConnection = class{(TEventEmitter)} external 'DataConnection'
  public
    //inherited from TEventEmitter
    function addListener(&type, listener, scope, once: variant): TEventEmitter; external 'addListener';
    function &on(&type, listener, scope, once: variant): TEventEmitter; external 'on';
    function once(&type, listener, scope: variant): TEventEmitter; external 'once';
    function removeListener(&type, listener, scope: variant): TEventEmitter; external 'removeListener';
    function off(&type, listener, scope: variant): TEventEmitter; external 'off';
    function removeAllListeners(&type: variant): TEventEmitter; external 'removeAllListeners';
    function listeners(&type: variant): variant; external 'listeners';
    function emit(&type: variant): boolean; external 'emit';   //vararg function
  public
    constructor Create(peer: TPeer; provider, options: variant); external 'Peer.connect.DataConnection';
    procedure initialize(DataChannel: variant); external 'initialize';
    procedure close; external 'close';
    procedure send(data: variant; chunked: boolean); external 'send';
    procedure handleMessage(message: variant); external 'handleMessage';
  end;

  JMediaConnection = class{(TEventEmitter)} external 'mediaConnection'
  public
    //inherited from EventEmitter
    function addListener(&type, listener, scope, once: variant): TEventEmitter; external 'addListener';
    function &on(&type, listener, scope, once: variant): TEventEmitter; external 'on';
    function once(&type, listener, scope: variant): TEventEmitter; external 'once';
    function removeListener(&type, listener, scope: variant): TEventEmitter; external 'removeListener';
    function off(&type, listener, scope: variant): TEventEmitter; external 'off';
    function removeAllListeners(&type: variant): TEventEmitter; external 'removeAllListeners';
    function listeners(&type: variant): variant; external 'listeners';
    function emit(&type: variant): boolean; external 'emit';   //vararg function
  public
    constructor Create(peer: TPeer; provider, options: variant); external 'Peer.call.MediaConnection';
    procedure addStream(remoteStream: variant); external 'addStream';
    procedure handleMessage(message: variant); external 'handleMessage';
    procedure answer(stream: variant); external 'answer';
    procedure close; external 'close';
  end;

  JNegotiator = class external 'Negotiator'
  public
    procedure startConnection(connection, options: variant); external 'startConnection';
    procedure cleanup(connection: variant); external 'cleanup';
    procedure handleSDP(&type, connection, sdp: variant); external 'handleSDP';
    procedure handleCandidate(connection, ice: variant); external 'handleCandidate';
  end;

  JSocket = class{(TEventEmitter)} external 'Socket'
  public
    //inherited from EventEmitter
    function addListener(&type, listener, scope, once: variant): TEventEmitter; external 'addListener';
    function &on(&type, listener, scope, once: variant): TEventEmitter; external 'on';
    function once(&type, listener, scope: variant): TEventEmitter; external 'once';
    function removeListener(&type, listener, scope: variant): TEventEmitter; external 'removeListener';
    function off(&type, listener, scope: variant): TEventEmitter; external 'off';
    function removeAllListeners(&type: variant): TEventEmitter; external 'removeAllListeners';
    function listeners(&type: variant): variant; external 'listeners';
    function emit(&type: variant): boolean; external 'emit';   //vararg function
  public
    constructor Create(secure: boolean; host: string; port: integer; path, key: string); external 'Socket';
    procedure start(id: string; token: string); external 'start';
    procedure send(data: variant); external 'send';
    procedure close; external 'close';
  end;

implementation


end.

链接到 github 上的 peer.js
https://github.com/peers/peerjs/blob/master/lib/peer.js

如何正确包装此文件中的类?

4

1 回答 1

3

peerjs 中的匿名函数用于创建私有作用域。

在 Pascal 术语中,匿名函数内部的内容就像“实现”部分中的代码,分配给“导出”的内容将被公开,有点像“接口”部分。

因此外部无法访问 binaryFeatures 变量(至少不能从该代码片段访问)。

与其从 JS 代码开始,不如从文档开始,查看代码只是为了填补文档中的漏洞/歧义。

此外,由于 JS 没有适当的可见性管理,“私有”方法和字段通过混合隐蔽和匿名函数来模仿。例如,peerjs 源中以“_”为前缀的方法旨在作为私有/受保护的,因此您不应该公开它们,即使它们可以在 JS 中访问。

因此,您可以从 Peer 对象开始,公开其方法,然后公开这些方法使用/需要的对象。

其他要知道的事情:

  • 参数名称是无意义的,因此可以随意重命名它们并随意使用 Pascal 约定,或者在库使用晦涩/短名称时使用有意义的长名称
  • 支持原型类继承,因此“JSubClass = class (JParent)”是可以的(但要求是 JParent 应该支持“new”运算符,否则,库可能会提供自定义构造函数或工厂)
  • 仅当名称不同时才需要方法的外部指令,如果您使用了友好的 Pascal 名称

所以

procedure start(id, token: string); external 'start';

procedure start(id, token: string);

是相同的,但如果你“Pascalized”这个名字,它变得有必要:

procedure Start(id, token: string); external 'start';

因为 JS 区分大小写

于 2014-12-19T09:50:02.010 回答