zoukankan      html  css  js  c++  java
  • WebAssembly迁移指南

    P)NaCl弃用公告

    鉴于跨浏览器WebAssembly支持的势头,我们计划将我们的本机代码工作重点放在WebAssembly上,并计划在2018年第一季度删除对PNaCl的支持(Chrome应用除外)。我们相信围绕WebAssembly的充满活力的生态系统 使其更适合新的和现有的高性能Web应用程序,并且PNaCl的使用率足够低以保证弃用。

    我们最近还宣布了 ChromeOS以外的Chrome应用程序 2018年第一季度的弃用 。

    工具链迁移

    对于大多数(P)NaCl用例,我们建议从NaCl SDK转换到Emscripten。如果您的应用程序可移植到Linux,使用SDL或POSIX API ,则迁移可能相当简单 。虽然没有直接支持NaCl / Pepper API,但我们试图列出Web API等价物。对于更具挑战性的移植案例,请与 本地客户讨论@ googlegroups联系。COM

    API迁移

    我们在此概述了Web平台替代每个暴露于(P)NaCl的API的状态。此外,该表列出了Emscripten中提供最接近替代品的库或选项。

    我们希望在2017年为WebAssembly添加共享内存线程支持,因为线程对匹配(P)NaCl最有趣的用例至关重要。假定即将支持线程的迁移项目标记如下。如果您的应用程序的流控制在很大程度上依赖于阻止API,您可能还会发现需要线程支持才能方便地移植。

    虽然我们在此表中试图准确,但毫无疑问会有错误或遗漏。如果您遇到一个,请通过 native-client-discuss @googlegroups联系我们。COM

    PPAPI

    PPB_Audio

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create X SDL(部分) GAP(部分) - AudioWorkletNode相当于ROUGHLY 仍在标准化。
    GetCurrentConfig   SDL AudioContext.*(获取传入的设置)  
    StartPlayback   SDL AudioBufferSourceNode.start  
    StopPlayback   SDL AudioBufferSourceNode.stop  

    PPB_AudioBuffer

    PPAPI方法 假设线程 Emscripten Web API 限制
    GetTimestamp   SDL AudioBufferSourceNode.start(parameter) 每次传递而不是附加到缓冲区。
    setTimestamp   SDL AudioBufferSourceNode.start(parameter)  
    GetSampleRate   SDL AudioBuffer.sampleRate  
    GetSampleSize   GAP GAP - WebAudio仅使用32位浮点数,PPAPI使用16位int。 PPAPI理论上支持多种采样大小。实际上,它只支持16位采样。不幸的是,开发人员已经要求16位样本大小以节省内存使用。
    GetNumberOfChannels   SDL AudioBuffer.numberOfChannels  
    GetDataBuffer   SDL AudioBuffer.getChannelData  
    GetBufferSize   SDL AudioBuffer.length  

    PPB_AudioConfig

    PPAPI方法 假设线程 Emscripten Web API 限制
    CreateStereo16Bit   GAP GAP - 仅支持32位浮点样本  
    GetSampleRate   SDL AudioContext.sampleRate  
    GetSampleFrameCount   SDL AudioBuffer.length  
    RecommendSampleRate   SDL AudioContext.sampleRate(来自默认构造) 默认情况下,AudioContext将具有首选采样率。
    RecommendSampleFrameCount   GAP GAP - 没有获得推荐缓冲区大小的机制。  

    PPB_Console

    PPAPI方法 假设线程 Emscripten Web API 限制
    Log   UTIME console.log/warn/error/...  
    LogWithSource   GAP GAP PPAPI提供了一种覆盖控制台消息中的源文件名和行号的方法。(虽然JS API提供了样式文本的方法)。

    PPB_Core

    PPAPI方法 假设线程 Emscripten Web API 限制
    getTime   utime new Date().getTime()  
    getTimeTicks   utime new Date().getTime()  
    IsMainThread   GAP window.document !== undefined  
    CallOnMainThread   GAP Worker.postMessage + Atomics.wait 可以构建等效同步。

    PPB_FileIO

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   FS (partial) FileReader / FileWrite (Entry.createReader / Entry.createWriter) 创建和打开使用的方式不同,但这些部分具有相同的功能。
    Open   FS (partial) FileReader / FileWrite (Entry.createReader / Entry.createWriter)  
    Query   FS (partial) Entry.getMetadata  
    Touch   FS (partial) GAP (partial) - No direct equivalent, but no access time either. 修改时间可以通过写入来提高。
    Read   FS (partial) Entry.getFile + Blob.slice + FileReader.getBinaryData 请注意,此API需要额外的副本才能读取线性内存,如果Blob切片未使用mmap进行优化,则可能会更糟。
    Write   FS (partial) FileWriter.seek + FileWriter.write 'write*' Events  
    SetLength   FS (partial) FileWriter.truncate + 'write*' Events  
    Flush   GAP GAP - No equivalent, no way to flush.  
    Close   FS (partial) No equivalent, open files and directories are implicitly closed.  
    ReadToArray   GAP GAP - No equivalent. 允许并行多个子范围读取。

    PPB_FileRef

     

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   FS (partial) Entry.getFile(..., {create:true})  
    GetFileSystemType   FS (partial) FileSystem.type  
    GetName   FS (partial) Entry.name  
    GetPath   FS (partial) Entry.fullPath  
    GetParent   FS (partial) Entry.getParent  
    MakeDirectory   FS (partial) Entry.getDirectory(..., {create:true})  
    Touch   FS (partial) GAP (partial) - No direct equivalent, but no access time either. 修改时间可以通过写入来提高。
    Delete   FS (partial) Entry.remove  
    Rename   FS (partial) Entry.moveTo  
    Query   GAP Entry.getMetadata GAP - JS API具有文件大小和上次修改日期,但没有创建日期和上次访问日期。
    ReadDirectoryEntries   FS (partial) Directory.readEntries  

    PPB_FileSystem

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   FS (partial) window.requestFileSystem JS API只需一步即可完成
    Open   GAP window.requestFileSystem GAP - Filesystems API仅限chrome。IndexedDB在子范围写入方面具有额外的性能限制。
    GetType   GAP FileSystem.type  

    PPB_Fullscreen

    PPAPI方法 假设线程 Emscripten Web API 限制
    IsFullScreen   html5.h Document.fullscreenEnabled  
    SetFullscreen   html5.h Document.requestFullscreen  
    GetScreenSize   html5.h Document.exitFullscreen  

    PPB_Gamepad

    PPAPI方法 假设线程 Emscripten Web API 限制
    Sample   SDL Gamepad.* GAP - PPAPI公开了一个时间戳值,但JS API没有提供这个(虽然它是规范的)。

    PPB_Graphics2D

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   SDL Canvas.getContext('2d')  
    Describe   SDL Canvas.clientWidth + Canvas.clientHeight  
    PaintImageData   SDL CanvasRenderingContext2d.putImageData  
    Scroll   GAP CanvasRenderingContext2d.scrollIntoView GAP(部分) - 不完全匹配(可能必须求助于getImageData + putImageData,这将很慢)。不是跨浏览器标准。
    ReplaceContents   SDL CanvasRenderingContext2d.drawImage  
    Flush   GAP GAP - 仅返回事件循环会触发刷新。  
    SetScale   SDL CanvasRenderingContext2d.scale  
    GetScale   SDL CanvasRenderingContext2d.currentTransform  
    SetLayerTransform   SDL CanvasRenderingContext2d.setTransform CanvasRenderingContext2d.scale CanvasRenderingContext2d.translate  

    PPB_Graphics3D

    PPAPI方法 假设线程 Emscripten Web API 限制
    GetAttribMaxValue  
    GAP
    GAP - Canvas.getContext允许您设置请求某些大小的深度/模板缓冲区的布尔值,但无法查询可能的内容(或者获取除了开启或关闭之外的任何内容)  
    Create   SDL Canvas.getContext  
    GetAttribs   SDL WebGLRenderingContext.getContextAttributes  
    SetAttribs   SDL Canvas.getContext(.., OPTIONS)  
    GetError   SDL WebGLRenderingContext.getError  
    ResizeBuffers   SDL Canvas.width = w; Canvas.height = h;  
    SwapBuffers   GAP GAP - 无法显式翻转帧,必须返回事件循环.  

    PPB_ImageData

    PPAPI方法 假设线程 Emscripten Web API 限制
    GetNativeImageDataFormat   SDL ImageData mandates RGBA order  
    IsImageDataFormatSupported   SDL ImageData mandates RGBA order  
    Create   SDL CanvasRenderingContext2d.createImageData  
    Describe   SDL ImageData never has a stride  
    Map   SDL ImageData.data  
    Unmap   SDL ImageData.data  

    PPB_InputEvent

    PPAPI方法 假设线程 Emscripten Web API 限制
    RequestInputEvents   SDL 没有直接的等价物

    由于JS / Wasm在主线程上运行,

    并且可以更便宜地过滤事件而不

    会导致跨进程往返,因此缺少此

    功能可能不太相关。

    RequestFilteringInputEvents   SDL mouse* key* wheel* touch* composition* Events  
        SDL Element.addEventListener  
    ClearInputEventRequest   SDL Element.removeEventListener  
    GetType   SDL Event class descendants  
    GetTimeStamp   SDL Event.timeStamp  
    GetModifiers   SDL *Event.altKey/shiftKey/metaKey/ctrlKey  

    PPB_MouseInputEvent

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   SDL MouseEvent  
    GetButton   SDL MouseEvent.button  
    GetPosition   SDL MouseEvent.client*/page*/offset*  
    GetClickCount   SDL dblclick' vs 'mousedown' Events  
    GetMovement   SDL MouseEvent.movement*  

    PPB_WheelInputEvent

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   SDL WheelEvent  
    GetDelta   SDL WheelEvent.delta *  
    GetTicks   GAP GAP - deltaMode有点包含此信息,但不完整。  
    GetScrollByPage   GAP GAP - deltaMode有点包含此信息,但不完整。  

    PPB_KeyboardInputEvent

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   SDL 的KeyboardEvent  
    GetKeyCode   SDL KeyboardEvent.keyCode  
    GetCharacterText   SDL KeyboardEvent.key  
    GetScrollByPage   SDL KeyboardEvent.code  

    PPB_TouchInputEvent

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   SDL 的TouchEvent  
    AddTouchPoint   SDL TouchEvent.touches.push  
    GetTouchCount   SDL TouchEvent.touches.length  
    GetTouchByIndex   SDL TouchEvent.touches [I]  
    GetTouchById   SDL Touch.indentifer(自己想出来)  

    PPB_IMEInputEvent

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   GAP CompositionEvent  
    getText   GAP CompositionEvent.data  
    GetSegmentNumber   GAP GAP - 没有直接的等价物  
    GetSegmentOffset   GAP GAP - 没有直接的等价物  
    GetTargetSegment   GAP GAP - 没有直接的等价物  
    GetSelection   GAP GAP - 没有直接的等价物  

    PPB_Instance

    PPAPI方法 假设线程 Emscripten Web API 限制
    BindGraphics   SDL Canvas.getContext(作为绑定是自动的)。  
    IsFullFrame   GAP GAP - 不等同于mime类型处理程序。 可以注册NaCl应用程序来处理特定的mime类型并拥有整个文档。

    PPB_MediaStreamAudioTrack

    PPAPI方法 假设线程 Emscripten Web API 限制
    配置   GAP GAP - 没有等价物  
    GetAttrib   GAP MediaStreamSettings.channelCount  
        GAP MediaStreamSettings.sampleSize  
        GAP MediaStreamSettings.sampleRate  
        GAP GAP - 不等同于PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS  
        GAP GAP - 不等同于PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION  
    GetId   GAP MediaStream.id  
    HasEnded   GAP MediaStream.ended  
    GetBuffer   GAP GAP - 没有等价物  
    RecycleBuffer   GAP GAP - 没有等价物  
    Close     GAP - 没有等价物  

    PPB_MediaStreamVideoTrack

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   GAP GAP - 没有等价物 能够创建合成流。
    Configure   GAP GAP - 没有等价物  
    GetAttrib   GAP MediaStreamSettings.width  
        GAP MediaStreamSettings.height  
        GAP GAP - 不等同于PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES  
        GAP GAP - 不等同于PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT  
    GetId   GAP MediaStream.id  
    HasEnded   GAP MediaStream.ended  
    getFrame   GAP GAP - 没有等价物  
    RecycleFrame   GAP GAP - 没有等价物  
    Close   GAP GAP - 没有等价物  
    GetEmptyFrame   GAP GAP - 没有等价物  
    PutFrame   GAP GAP - 没有等价物  

    PPB_MessageLoop

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   N / A 工人得到一个隐含的事件循环。  
    GetForMainThread   N / A 工人得到一个隐含的事件循环。  
    GetCurrent   N / A 工人得到一个隐含的事件循环。  
    AttachToCurrentThread   N / A 工人得到一个隐含的事件循环。  
    Run   N / A 工人得到一个隐含的事件循环。  
    PostWork   N / A 工人得到一个隐含的事件循环。  
    PostQuit   N / A 工人得到一个隐含的事件循环。  

    PPB_Messaging

    PPAPI方法 假设线程 Emscripten Web API 限制
    PostMessage的   N / A Window.postMessage  
    RegisterMessageHandler   N / A Window.addEventListener  
    UnregisterMessageHandler   N / A Window.removeEventListener  

    PPB_MouseCursor

    PPAPI方法 假设线程 Emscripten Web API 限制
    setCursor   SDL Element.style.cursor 支持相同的库存光标集。自定义游标可以使用url(..)完成。动态自定义游标可以使用数据URI完成。CSS3支持指定热点。

    PPB_MouseLock

    PPAPI方法 假设线程 Emscripten Web API 限制
    LockMouse   SDL Element.requestPointerLock  
    UnlockMouse   SDL Element.exitPointerLock  

    PPB_OpenGLES2

    PPAPI方法 假设线程 Emscripten Web API 限制
    Several Methods   OpenGLES 在功能上接近WebGL 1.0。  
      X   GAP - 没有屏幕外画布,渲染必须在主线程上完成。  

    PPB_TextInputController

    PPAPI方法 假设线程 Emscripten Web API 限制
    SetTextInputType   GAP GAP - 没有关于浏览器包含输入的等效提示。 一些开发人员希望能够以这种方式提示,或者最好能够在画布内嵌入和显示内联的IME事件/输出。
    UpdateCaretPosition   GAP GAP - 没有关于浏览器包含输入的等效提示。  
    CancelCompositionText   GAP GAP - 没有关于浏览器包含输入的等效提示。  
    UpdateSurroundingText   GAP GAP - 没有关于浏览器包含输入的等效提示。  

    PPB_URLLoader

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   embind new XMLHttpRequest();  
    Open   embind XMLHttpRequest.open  
    FollowRedirect   embind Request.redirect  
        GAP GAP - 没有XMLHTTPRequest等价物  
    GetUploadProgress   embind XMLHttpRequest'progress'事件  
        GAP GAP - 没有等效的Fetch API  
    GetDownloadProgress   embind XMLHttpRequest'progress'事件  
        GAP GAP - 没有等效的Fetch API  
    GetResponseInfo   embind XMLHttpRequest.getAllResponseHeaders  
        embind 获取响应。*  
    ReadResponseBody   embind XMLHttpRequest.response  
        embind 身体。*(响应是身体)  
    FinishStreamingToFile   embind GAP - 没有直接的等价物 XMLHttpRequest和Fetch都假设流式传输到内存,而不是直接到存储。
    Close   embind XMLHttpRequest.abort  
        GAP GAP - 没有等效的Fetch API  

    PPB_URLRequestInfo

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   embind XMLHttpRequest的  
        embind 获取请求 无法流式传输到文件。
    SetProperty   GAP GAP - 没有XMLHttpRequest的直接等价物 XMLHttpRequest不提供重定向后的每个请求限制的直接方法,流式传输到文件,设置引用者或凭据策略。
        embind 请求。*  
    AppendDataToBody   embind XMLHttpRequest.send GAP - 两者都必须拥有整个身体,而不是一块。
        embind fetch(..,options:body)  
    AppendFileToBody   GAP GAP - 没有直接的等价物  
        N / A <FORM> 您也可以使用FileReader阅读并上传,但这更像是AppendDataToBody

    PPB_URLResponseInfo

    PPAPI方法 假设线程 Emscripten Web API 限制
    getProperty   embind XMLHttpRequest.getAllResponseHeaders + others  
        embind Fetch Response.*  
    GetBodyAsFileRef   embind Fetch Response (Body) .blob() 假设存储层优化传输。

    PPB_Var

    PPAPI方法 假设线程 Emscripten Web API 限制
    VarFromUtf8   embind TextDecoder.decode  
    VarToUtf8   embind TextEncoder.encode  
    VarFromResource   N / A N / A  
    VarToResource   N / A N / A  

    PPB_VarArray

    PPAPI方法 假设线程 Emscripten Web API 限制
    Get   embind 阵列[I]  
    Set   embind 数组[i] = x  
    GetLength   embind Array.length  
    SetLength   embind Array.length = n  

    PPB_VarArrayBuffer

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   embind new ArrayBuffer(n)  
    ByteLength   embind ArrayBuffer.byteLength  
    Map   GAP GAP - 没有直接的等价物 Asm.js / Wasm模块无法映射除单个线性内存堆之外的ArrayBuffer区域。未来的多个记忆或内存映射可能会改善这一点
    Unmap   GAP GAP - 没有直接的等价物  

    PPB_VarDictionary

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   embind {}  
    Get   embind <Object>[i]  
    Set   embind <Object>[i] = x  
    Delete   embind delete <Object>[i]  
    HasKey   embind x in <Object>  
    GetKeys   embind for (k in <Object>) {} 没有字面上的等价物,但它可以构建。

    PPB_VideoDecoder

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   GAP GAP - No equivalent  
    Initialize   GAP GAP - No equivalent  
    Decode   GAP GAP - No equivalent  
    GetPicture   GAP GAP - No equivalent  
    RecyclePicture   GAP GAP - No equivalent  
    Flush   GAP GAP - No equivalent  
    Reset   GAP GAP - No equivalent  

    PPB_VideoEncoder

    PPAPI方法 假设线程 Emscripten Web API 限制
    Create   GAP GAP - No equivalent Overlap with MediaRecorder API, but not exact.
    GetSupportedProfiles   GAP GAP - No equivalent  
    Initialize   GAP GAP - No equivalent  
    GetFramesRequired   GAP GAP - No equivalent  
    GetFrameCodedSize   GAP GAP - No equivalent  
    GetVideoFrame   GAP GAP - No equivalent  
    Encode   GAP GAP - No equivalent  
    GetBitstreamBuffer   GAP GAP - No equivalent  
    RecycleBitstreamBuffer   GAP GAP - No equivalent  
    RequestEncodingParametersChange   GAP GAP - No equivalent  
    Close   GAP GAP - No equivalent

    PPB_VideoFrame

    PPAPI方法 假设线程 Emscripten Web API 限制
    GetTimestamp   间隙 GAP - 没有等价物  
    setTimestamp   间隙 GAP - 没有等价物  
    getFormat   间隙 GAP - 没有等价物  
    getSize   间隙 GAP - 没有等价物  
    GetDataBuffer   间隙 GAP - 没有等价物  
    GetDataBufferSize   间隙 GAP - 没有等价物  

    PPB_View

    PPAPI方法 假设线程 Emscripten Web API 限制
    GetRect   embind Element.getBoundingClientRect  
    IsFullscreen   embind Document.fullScreenEnabled 与文档相关而不仅仅是单个元素。
    ISVISIBLE   embind IntersectionObserver  
    IsPageVisible   embind document.visibilityState  
    GetClipRect   embind IntersectionObserver  
    GetDeviceScale   embind window.devicePixelRatio  
    GetCSSScale   embind <Element> .getBoundingClientRect()。width / <Element> .offsetWidth  
    GetScrollOffset   embind <Element> .scrollTop / <Element> .scrollLeft  

    PPB_WebSocket

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   GAP WebSocket.WebSocket  
    Connect   GAP WebSocket.WebSocket(url, ...) WebSocket 'open' Event  
    Close   GAP WebSocket.close  
    ReceiveMessage   GAP WebSocket 'message' Event WebSocket 'error' Event WebSocket 'close' Event  
    SendMessage   GAP WebSocket.send  
    GetBufferedAmount   GAP WebSocket.bufferedAmount  
    GetCloseCode   GAP CloseEvent.code  
    GetCloseReason   GAP CloseEvent.reason  
    GetCloseWasClean   GAP CloseEvent.wasClean  
    GetExtensions   GAP WebSocket.extensions  
    GetProtocol   GAP WebSocket.protocol  
    GetReadyState   GAP WebSocket.readyState  
    GetURL   GAP WebSocket.url  

    PPP_Graphics3D

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Graphics3DContextLost   SDL Canvas 'webglcontextlost' Event  

    PPP_InputEvent

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    HandleInputEvent   SDL Element.addEventListener  

    PPP_Instance

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    DidCreate   N/A <Element>[key] General DOM access lets you fish out tag attributes
    DidDestroy   N/A N/A Not triggered for NaCl
    DidChangeView   N/A Element 'resize' Event  
    DidChangeFocus   N/A Element 'focus', 'focusin', 'focusout' Events  
    HandleDocumentLoad   N/A GAP - No way to register as a mime type handler NaCl modules via apps + a manifest entry can be set up to handle particular mime types.

    PPP_MessageHandler

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    HandleMessage   embind MessagePort 'message' Event Window 'message' Event  
    HandleBlockingMessage   N/A GAP - No direct equivalent Similar synchronization can be done off main thread with Atomics.wait. This was added to support emulation of synchronous plugin APIs.

    PPP_Messaging

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    HandleMessage   embind MessagePort 'message' Event Window 'message' Event  

    PPP_MouseLock

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    MouseLockLost   SDL Element 'pointerlockchange', 'pointerlockerror' Events  

    IRT

    PPB_Audio

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create x SDL (partial) GAP (partial) - AudioWorkletNode ROUGHLY equivalent Still being standardized.
    GetCurrentConfig   SDL AudioContext.* (gets back settings passed in)  
    StartPlayback   SDL AudioBufferSourceNode.start  
    StopPlayback   SDL AudioBufferSourceNode.stop  

    PPB_AudioBuffer

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    GetTimestamp   SDL AudioBufferSourceNode.start (parameter) Passed in each time instead of attached to the buffer.
    SetTimestamp   SDL AudioBufferSourceNode.start (parameter)  
    GetSampleRate   SDL AudioBuffer.sampleRate  
    GetSampleSize   GAP GAP - WebAudio only uses 32-bit float, PPAPI does 16-bit int. PPAPI theoretically supports multiple sampling sizes. In practice, it only supports 16-bit samples. Unfortunately, developers have requested 16-bit sample sizes to save on memory use.
    GetNumberOfChannels   SDL AudioBuffer.numberOfChannels  
    GetDataBuffer   SDL AudioBuffer.getChannelData  
    GetBufferSize   SDL AudioBuffer.length  

    PPB_AudioConfig

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    CreateStereo16Bit   GAP GAP - Only 32-bit float samples supported  
    GetSampleRate   SDL AudioContext.sampleRate  
    GetSampleFrameCount   SDL AudioBuffer.length  
    RecommendSampleRate   SDL AudioContext.sampleRate (from default construct) An AudioContext will have the preferred sampling rate by default.
    RecommendSampleFrameCount   GAP GAP - No mechanism to get a recommended buffer size.  

    PPB_Console

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Log   utime console.log/warn/error/...  
    LogWithSource   GAP GAP PPAPI provides a way to override the source filename and line number in a console message. (Though JS API provides way to style text).

    PPB_Core

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    getTime   utime new Date().getTime()  
    getTimeTicks   utime new Date().getTime()  
    IsMainThread   GAP window.document !== undefined  
    CallOnMainThread   GAP Worker.postMessage + Atomics.wait Equivalent synchronization can be built.

    PPB_FileIO

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   FS (partial) FileReader / FileWrite (Entry.createReader / Entry.createWriter) Create and open are used differently, but the pieces are of equal power.
    Open   FS (partial) FileReader / FileWrite (Entry.createReader / Entry.createWriter)  
    Query   FS (partial) Entry.getMetadata  
    Touch   FS (partial) GAP (partial) - No direct equivalent, but no access time either. Modify time can be bumped by writing.
    Read   FS (partial) Entry.getFile + Blob.slice + FileReader.getBinaryData Note, this API requires an extra copy to get a read into linear memory, and may be worse than that if Blob slices are not optimizes to use mmap.
    Write   FS (partial) FileWriter.seek + FileWriter.write 'write*' Events  
    SetLength   FS (partial) FileWriter.truncate + 'write*' Events  
    Flush   GAP GAP - No equivalent, no way to flush.  
    Close   FS (partial) No equivalent, open files and directories are implicitly closed.  
    ReadToArray   GAP GAP - No equivalent. Allows multiple subrange reads in parallel.

    PPB_FileRef

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   FS (partial) Entry.getFile(..., {create:true})  
    GetFileSystemType   FS (partial) FileSystem.type  
    GetName   FS (partial) Entry.name  
    GetPath   FS (partial) Entry.fullPath  
    GetParent   FS (partial) Entry.getParent  
    MakeDirectory   FS (partial) Entry.getDirectory(..., {create:true})  
    Touch   FS (partial) GAP (partial) - No direct equivalent, but no access time either. Modify time can be bumped by writing.
    Delete   FS (partial) Entry.remove  
    Rename   FS (partial) Entry.moveTo  
    Query   GAP Entry.getMetadata GAP - JS API has file size and last modified date, but doesn't have creation date and last accessed date.
    ReadDirectoryEntries   FS (partial) Directory.readEntries  

    PPB_FileSystem

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   FS (partial) window.requestFileSystem JS API does both in one step
    Open   GAP window.requestFileSystem GAP - Filesystems API is chrome only. IndexedDB has additional performance limitations around subrange writes.
    GetType   GAP FileSystem.type  

    PPB_Fullscreen

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    IsFullScreen   html5.h Document.fullscreenEnabled  
    SetFullscreen   html5.h Document.requestFullscreen  
    GetScreenSize   html5.h Document.exitFullscreen  

    PPB_Gamepad

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Sample   SDL Gamepad.* GAP - PPAPI exposes a timestamp value, but the JS API doesn't provide this (though it is spec'd).

    PPB_Graphics2D

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   SDL Canvas.getContext('2d')  
    Describe   SDL Canvas.clientWidth + Canvas.clientHeight  
    PaintImageData   SDL CanvasRenderingContext2d.putImageData  
    Scroll   GAP CanvasRenderingContext2d.scrollIntoView GAP (partial) - Not an exact match (might have to resort to getImageData + putImageData which will be slow). Not a cross-browser standard.
    ReplaceContents   SDL CanvasRenderingContext2d.drawImage  
    Flush   GAP GAP - Only returning to the event loop triggers the flush.  
    SetScale   SDL CanvasRenderingContext2d.scale  
    GetScale   SDL CanvasRenderingContext2d.currentTransform  
    SetLayerTransform   SDL CanvasRenderingContext2d.setTransform CanvasRenderingContext2d.scale CanvasRenderingContext2d.translate  

    PPB_Graphics3D

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    GetAttribMaxValue   GAP GAP - Canvas.getContext lets you set booleans requesting depth / stencil buffers of certain sizes, but does not have a way to query what's possible (or get anything other than on or off for each)  
    Create   SDL Canvas.getContext  
    GetAttribs   SDL WebGLRenderingContext.getContextAttributes  
    SetAttribs   SDL Canvas.getContext(.., OPTIONS)  
    GetError   SDL WebGLRenderingContext.getError  
    ResizeBuffers   SDL Canvas.width = w; Canvas.height = h;  
    SwapBuffers   GAP GAP - No way to explicitly flip a frame, must return to the event loop.  

    PPB_ImageData

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    GetNativeImageDataFormat   SDL ImageData mandates RGBA order  
    IsImageDataFormatSupported   SDL ImageData mandates RGBA order  
    Create   SDL CanvasRenderingContext2d.createImageData  
    Describe   SDL ImageData never has a stride  
    Map   SDL ImageData.data  
    Unmap   SDL ImageData.data  

    PPB_InputEvent

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    RequestInputEvents   SDL No direct equivalent The lack of this feature is probably less relevant as JS / Wasm runs on the main thread and can more cheaply filter events without incurring a cross process round-trip.
    RequestFilteringInputEvents   SDL mouse* key* wheel* touch* composition* Events  
        SDL Element.addEventListener  
    ClearInputEventRequest   SDL Element.removeEventListener  
    GetType   SDL Event class descendants  
    GetTimeStamp   SDL Event.timeStamp  
    GetModifiers   SDL *Event.altKey/shiftKey/metaKey/ctrlKey  

    PPB_MouseInputEvent

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   SDL MouseEvent  
    GetButton   SDL MouseEvent.button  
    GetPosition   SDL MouseEvent.client*/page*/offset*  
    GetClickCount   SDL dblclick' vs 'mousedown' Events  
    GetMovement   SDL MouseEvent.movement*  

    PPB_WheelInputEvent

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   SDL WheelEvent  
    GetDelta   SDL WheelEvent.delta*  
    GetTicks   GAP GAP - deltaMode kinda of contains this info, but incompletely.  
    GetScrollByPage   GAP GAP - deltaMode kinda of contains this info, but incompletely.  

    PPB_KeyboardInputEvent

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   SDL KeyboardEvent  
    GetKeyCode   SDL KeyboardEvent.keyCode  
    GetCharacterText   SDL KeyboardEvent.key  
    GetCode   SDL KeyboardEvent.code  

    PPB_TouchInputEvent

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   SDL TouchEvent  
    AddTouchPoint   SDL TouchEvent.touches.push  
    GetTouchCount   SDL TouchEvent.touches.length  
    GetTouchByIndex   SDL TouchEvent.touches[i]  
    GetTouchById   SDL Touch.indentifer (to figure this out yourself)  

    PPB_IMEInputEvent

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   GAP CompositionEvent  
    GetText   GAP CompositionEvent.data  
    GetSegmentNumber   GAP GAP - No direct equivalent  
    GetSegmentOffset   GAP GAP - No direct equivalent  
    GetTargetSegment   GAP GAP - No direct equivalent  
    GetSelection   GAP GAP - No direct equivalent  

    PPB_Instance

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    BindGraphics   SDL Canvas.getContext (moot as binding is automatic).  
    IsFullFrame   GAP GAP - No equivalent to mime type handlers. NaCl apps can be registered to handle a particular mime type and own the whole document.

    PPB_MediaStreamAudioTrack

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Configure   GAP GAP - No equivalent  
    GetAttrib   GAP MediaStreamSettings.channelCount  
        GAP MediaStreamSettings.sampleSize  
        GAP MediaStreamSettings.sampleRate  
        GAP GAP - no equivalent to PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS  
        GAP GAP - no equivalent to PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION  
    GetId   GAP MediaStream.id  
    HasEnded   GAP MediaStream.ended  
    GetBuffer   GAP GAP - No equivalent  
    RecycleBuffer   GAP GAP - No equivalent  
    Close   GAP GAP - No equivalent  

    PPB_MediaStreamVideoTrack

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   GAP GAP - No equivalent Ability to create synthetic stream.
    Configure   GAP GAP - No equivalent  
    GetAttrib   GAP MediaStreamSettings.width  
        GAP MediaStreamSettings.height  
        GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES  
        GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT  
    GetId   GAP MediaStream.id  
    HasEnded   GAP MediaStream.ended  
    GetFrame   GAP GAP - No equivalent  
    RecycleFrame   GAP GAP - No equivalent  
    Close   GAP GAP - No equivalent  
    GetEmptyFrame   GAP GAP - No equivalent  
    PutFrame   GAP GAP - No equivalent  

    PPB_MessageLoop

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   N/A Mostly moot, workers get an implicit event loop.  
    GetForMainThread   N/A Mostly moot, workers get an implicit event loop.  
    GetCurrent   N/A Mostly moot, workers get an implicit event loop.  
    AttachToCurrentThread   N/A Mostly moot, workers get an implicit event loop.  
    Run   N/A Mostly moot, workers get an implicit event loop.  
    PostWork   N/A Mostly moot, workers get an implicit event loop.  
    PostQuit   N/A Mostly moot, workers get an implicit event loop.  

    PPB_Messaging

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    PostMessage   N/A Window.postMessage  
    RegisterMessageHandler   N/A Window.addEventListener  
    UnregisterMessageHandler   N/A Window.removeEventListener  

    PPB_MouseCursor

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    SetCursor   SDL Element.style.cursor Same set of stock cursors are supported. Custom cursors can be done with url(..). Dynamic custom cursors can be done with data URIs. CSS3 supports specifying the hotspot.

    PPB_MouseLock

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    LockMouse   SDL Element.requestPointerLock  
    UnlockMouse   SDL Element.exitPointerLock  

    PPB_OpenGLES2

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Several Methods   OpenGLES Close to WebGL 1.0 in functionality.  
      x   GAP - Without offscreen canvas, rendering must be done on the main thread.  

    PPB_TextInputController

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    SetTextInputType   GAP GAP - No equivalent hints to browser about canvas containing input. Some developers would like to either be able to hint in this fashion, or preferably the ability to intercept and display IME events / output inline inside a canvas.
    UpdateCaretPosition   GAP GAP - No equivalent hints to browser about canvas containing input.  
    CancelCompositionText   GAP GAP - No equivalent hints to browser about canvas containing input.  
    UpdateSurroundingText   GAP GAP - No equivalent hints to browser about canvas containing input.  

    PPB_URLLoader

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   embind new XMLHttpRequest();  
    Open   embind XMLHttpRequest.open  
    FollowRedirect   embind Request.redirect  
        GAP GAP - No XMLHTTPRequest equivalent  
    GetUploadProgress   embind XMLHttpRequest 'progress' Event  
        GAP GAP - No Fetch API equivalent  
    GetDownloadProgress   embind XMLHttpRequest 'progress' Event  
        GAP GAP - No Fetch API equivalent  
    GetResponseInfo   embind XMLHttpRequest.getAllResponseHeaders  
        embind Fetch Response.*  
    ReadResponseBody   embind XMLHttpRequest.response  
        embind Body.* (Response is a Body)  
    FinishStreamingToFile   embind GAP - No direct equivalent XMLHttpRequest and Fetch both assume streaming to memory, rather than directly to a storage.
    Close   embind XMLHttpRequest.abort  
        GAP GAP - No Fetch API equivalent  

    PPB_URLRequestInfo

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   embind XMLHttpRequest  
        embind Fetch Request No way to stream to a file.
    SetProperty   GAP GAP - No direct equivalent for XMLHttpRequest XMLHttpRequest doesn't provide direct ways to per-request limit following redirects, stream to a file, set referrer or credentials policy.
        embind Request.*  
    AppendDataToBody   embind XMLHttpRequest.send GAP - Both must have the whole body, rather than a chunk.
        embind fetch(.., options:body)  
    AppendFileToBody   GAP GAP - No direct equivalent  
        N/A <form> You can also read with FileReader and upload, but that's more like AppendDataToBody

    PPB_URLResponseInfo

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    GetProperty   embind XMLHttpRequest.getAllResponseHeaders + others  
        embind Fetch Response.*  
    GetBodyAsFileRef   embind Fetch Response (Body) .blob() Assumes storage layer optimizes transfer.

    PPB_Var

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    VarFromUtf8   embind TextDecoder.decode  
    VarToUtf8   embind TextEncoder.encode  
    VarFromResource   N/A N/A  
    VarToResource   N/A N/A  

    PPB_VarArray

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Get   embind Array[i]  
    Set   embind Array[i] = x  
    GetLength   embind Array.length  
    SetLength   embind Array.length = n  

    PPB_VarArrayBuffer

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   embind new ArrayBuffer(n)  
    ByteLength   embind ArrayBuffer.byteLength  
    Map   GAP GAP - No direct equivalent Asm.js / Wasm modules are unable to map regions of an ArrayBuffer other than their single linear memory heap. Future multiple memories or memory mapping might improve this.
    Unmap   GAP GAP - No direct equivalent  

    PPB_VarDictionary

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   embind {}  
    Get   embind <Object>[i]  
    Set   embind <Object>[i] = x  
    Delete   embind delete <Object>[i]  
    HasKey   embind x in <Object>  
    GetKeys   embind for (k in <Object>) {} No literal equivalent, but it can be built.

    PPB_VideoDecoder

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   GAP GAP - No equivalent  
    Initialize   GAP GAP - No equivalent  
    Decode   GAP GAP - No equivalent  
    GetPicture   GAP GAP - No equivalent  
    RecyclePicture   GAP GAP - No equivalent  
    Flush   GAP GAP - No equivalent  
    Reset   GAP GAP - No equivalent  

    PPB_VideoEncoder

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   GAP GAP - No equivalent Overlap with MediaRecorder API, but not exact.
    GetSupportedProfiles   GAP GAP - No equivalent  
    Initialize   GAP GAP - No equivalent  
    GetFramesRequired   GAP GAP - No equivalent  
    GetFrameCodedSize   GAP GAP - No equivalent  
    GetVideoFrame   GAP GAP - No equivalent  
    Encode   GAP GAP - No equivalent  
    GetBitstreamBuffer   GAP GAP - No equivalent  
    RecycleBitstreamBuffer   GAP GAP - No equivalent  
    RequestEncodingParametersChange   GAP GAP - No equivalent  
    Close   GAP GAP - No equivalent  

    PPB_VideoFrame

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    GetTimestamp   GAP GAP - No equivalent  
    SetTimestamp   GAP GAP - No equivalent  
    GetFormat   GAP GAP - No equivalent  
    GetSize   GAP GAP - No equivalent  
    GetDataBuffer   GAP GAP - No equivalent  
    GetDataBufferSize   GAP GAP - No equivalent  

    PPB_View

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    GetRect   embind Element.getBoundingClientRect  
    IsFullscreen   embind Document.fullScreenEnabled Pertains to document instead of just single element.
    IsVisible   embind IntersectionObserver  
    IsPageVisible   embind document.visibilityState  
    GetClipRect   embind IntersectionObserver  
    GetDeviceScale   embind window.devicePixelRatio  
    GetCSSScale   embind <Element>.getBoundingClientRect().width / <Element>.offsetWidth  
    GetScrollOffset   embind <Element>.scrollTop / <Element>.scrollLeft  

    PPB_WebSocket

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create   GAP WebSocket.WebSocket  
    Connect   GAP WebSocket.WebSocket(url, ...) WebSocket 'open' Event  
    Close   GAP WebSocket.close  
    ReceiveMessage   GAP WebSocket 'message' Event WebSocket 'error' Event WebSocket 'close' Event  
    SendMessage   GAP WebSocket.send  
    GetBufferedAmount   GAP WebSocket.bufferedAmount  
    GetCloseCode   GAP CloseEvent.code  
    GetCloseReason   GAP CloseEvent.reason  
    GetCloseWasClean   GAP CloseEvent.wasClean  
    GetExtensions   GAP WebSocket.extensions  
    GetProtocol   GAP WebSocket.protocol  
    GetReadyState   GAP WebSocket.readyState  
    GetURL   GAP WebSocket.url  

    PPP_Graphics3D

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Graphics3DContextLost   SDL Canvas 'webglcontextlost' Event  

    PPP_InputEvent

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    HandleInputEvent   SDL Element.addEventListener  

    PPP_Instance

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    DidCreate   N/A <Element>[key] General DOM access lets you fish out tag attributes
    DidDestroy   N/A N/A Not triggered for NaCl
    DidChangeView   N/A Element 'resize' Event  
    DidChangeFocus   N/A Element 'focus', 'focusin', 'focusout' Events  
    HandleDocumentLoad   N/A GAP - No way to register as a mime type handler NaCl modules via apps + a manifest entry can be set up to handle particular mime types.

    PPP_MessageHandler

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    HandleMessage   embind MessagePort 'message' Event Window 'message' Event  
    HandleBlockingMessage   N/A GAP - No direct equivalent Similar synchronization can be done off main thread with Atomics.wait. This was added to support emulation of synchronous plugin APIs.

    PPP_Messaging

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    HandleMessage   embind MessagePort 'message' Event Window 'message' Event  

    PPP_MouseLock

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    MouseLockLost   SDL Element 'pointerlockchange', 'pointerlockerror' Events  

    PPAPI (Apps)

    PPB_HostResolver

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create x GAP GAP (partial) - No direct equivalent  
    Resolve x GAP GAP (partial) - No direct equivalent  
    GetCanonicalName x GAP GAP (partial) - No direct equivalent  
    GetNetAddressCount x GAP GAP (partial) - No direct equivalent  
    GetNetAddress x GAP GAP (partial) - No direct equivalent  

    PPB_NetAddress

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    CreateFromIPv4Address x GAP GAP (partial) - No direct equivalent  
    CreateFromIPv6Address x GAP GAP (partial) - No direct equivalent  
    GetFamily x GAP GAP (partial) - No direct equivalent  
    DescribeAsString x GAP GAP (partial) - No direct equivalent  
    DescribeAsIPv4Address x GAP GAP (partial) - No direct equivalent  
    DescribeAsIPv6Address x GAP GAP (partial) - No direct equivalent  

    PPB_NetworkList

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    GetCount x GAP GAP - No direct equivalent  
    GetName x GAP GAP - No direct equivalent  
    GetType x GAP GAP - No direct equivalent  
    GetState x GAP GAP - No direct equivalent  
    GetIpAddress x GAP GAP - No direct equivalent  
    GetDisplayName x GAP GAP - No direct equivalent  
    GetMTU x GAP GAP - No direct equivalent  

    PPB_NetworkMonitor

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create x GAP GAP - No direct equivalent  
    UpdateNetworkList x GAP GAP - No direct equivalent  

    PPB_NetworkProxy

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    GetProxyForURL x GAP GAP - No direct equivalent  

    PPB_TCPSocket

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create x GAP chrome.sockets.tcp.create WebSockets / WebRTC closest practical equivalent on open Web.
      x GAP chrome.sockets.tcpServer.create  
    Bind x GAP chrome.sockets.tcpServer.create  
    Connect x GAP chrome.sockets.tcp.connect  
    GetLocalAddress x GAP chrome.sockets.udp.SocketInfo  
    GetRemoteAddress x GAP chrome.sockets.udp.SocketInfo  
    Read x GAP onReceive* Events  
    Write x GAP chrome.sockets.tcp.send  
    Listen x GAP chrome.sockets.tcpServer.listen  
    Accept x GAP onAccept* Events  
    Close x GAP chrome.sockets.tcp.close  
      x GAP chrome.sockets.tcpServer.close  
    SetOption x GAP chrome.sockets.tcp.update  
      x GAP chrome.sockets.tcpServer.update  

    PPB_UDPSocket

    PPAPI Method Assumes Threads Emscripten Web API Limitations
    Create x GAP chrome.sockets.udp.create GAP (partial) - WebRTC closest practical open Web equivalent
    Bind x GAP chrome.sockets.udp.bind  
    GetBoundAddress x GAP chrome.sockets.udp.SocketInfo  
    RecvFrom x GAP onReceive* Events  
    SendTo x GAP chrome.sockets.udp.send  
    Close x GAP chrome.sockets.udp.close  
    SetOption x GAP chrome.sockets.udp.update  
    JoinGroup x GAP chrome.sockets.udp.joinGroup  
    LeaveGroup x GAP chrome.sockets.udp.leaveGroup

    CC-By 3.0许可下提供的内容

  • 相关阅读:
    Go语言专题
    计算机网络专题
    分布式系统理论专题
    Scala语言专题
    Zookeeper专题
    Java虚拟机专题
    Java并发编程专题
    git使用指南
    Oracle查询今天、昨天、本周、上周、本月、上月数据
    python3 装饰器
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049152.html
Copyright © 2011-2022 走看看