UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

157 lines (127 loc) 4.27 kB
# NoFlo - Flow-Based Programming for JavaScript # (c) 2014-2016 TheGrid (Rituwall Inc.) # NoFlo may be freely distributed under the MIT license # # Input Port (inport) implementation for NoFlo components BasePort = require './BasePort' IP = require './IP' class InPort extends BasePort constructor: (options, process) -> @process = null if not process and typeof options is 'function' process = options options = {} options ?= {} options.buffered ?= false options.control ?= false options.triggering ?= true if not process and options and options.process process = options.process delete options.process if process unless typeof process is 'function' throw new Error 'process must be a function' @process = process if options.handle unless typeof options.handle is 'function' throw new Error 'handle must be a function' @handle = options.handle delete options.handle super options @prepareBuffer() attachSocket: (socket, localId = null) -> # Assign a delegate for retrieving data should this inPort # have a default value. if @hasDefault() if @handle socket.setDataDelegate => new IP 'data', @options.default else socket.setDataDelegate => @options.default socket.on 'connect', => @handleSocketEvent 'connect', socket, localId socket.on 'begingroup', (group) => @handleSocketEvent 'begingroup', group, localId socket.on 'data', (data) => @validateData data @handleSocketEvent 'data', data, localId socket.on 'endgroup', (group) => @handleSocketEvent 'endgroup', group, localId socket.on 'disconnect', => @handleSocketEvent 'disconnect', socket, localId socket.on 'ip', (ip) => @handleIP ip, localId handleIP: (ip, id) -> return if @process return if @options.control and ip.type isnt 'data' ip.owner = @nodeInstance ip.index = id if ip.scope @scopedBuffer[ip.scope] = [] unless ip.scope of @scopedBuffer buf = @scopedBuffer[ip.scope] else buf = @buffer buf.push ip buf.shift() if @options.control and buf.length > 1 if @handle @handle ip, @nodeInstance @emit 'ip', ip, id handleSocketEvent: (event, payload, id) -> # Handle buffering the old way if @isBuffered() @buffer.push event: event payload: payload id: id # Notify receiver if @isAddressable() @process event, id, @nodeInstance if @process @emit event, id else @process event, @nodeInstance if @process @emit event return if @process if @isAddressable() @process event, payload, id, @nodeInstance else @process event, payload, @nodeInstance # Emit port event return @emit event, payload, id if @isAddressable() @emit event, payload hasDefault: -> return @options.default isnt undefined prepareBuffer: -> @buffer = [] @scopedBuffer = {} validateData: (data) -> return unless @options.values if @options.values.indexOf(data) is -1 throw new Error "Invalid data='#{data}' received, not in [#{@options.values}]" # Returns the next packet in the (legacy) buffer receive: -> unless @isBuffered() throw new Error 'Receive is only possible on buffered ports' @buffer.shift() # Returns the number of data packets in a (legacy) buffered inport contains: -> unless @isBuffered() throw new Error 'Contains query is only possible on buffered ports' @buffer.filter((packet) -> return true if packet.event is 'data').length # Fetches a packet from the port get: (scope) -> if scope return undefined unless scope of @scopedBuffer buf = @scopedBuffer[scope] else buf = @buffer return if @options.control then buf[buf.length - 1] else buf.shift() # Returns the number of data packets in an inport length: (scope) -> if scope return 0 unless scope of @scopedBuffer return @scopedBuffer[scope].length return @buffer.length # Tells if buffer has packets or not ready: (scope) -> return @length(scope) > 0 module.exports = InPort