diff --git a/lang/node-arduino-firmata/Makefile b/lang/node-arduino-firmata/Makefile new file mode 100644 index 0000000000..a34c2ceb89 --- /dev/null +++ b/lang/node-arduino-firmata/Makefile @@ -0,0 +1,63 @@ +# +# Copyright (C) 2014 Arduino LLC +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NPM_NAME:=arduino-firmata +PKG_NAME:=node-$(PKG_NPM_NAME) +PKG_VERSION:=0.3.3 +PKG_RELEASE:=1 + +PKG_SOURCE:=v$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/shokai/node-arduino-firmata/archive/ + +PKG_BUILD_DEPENDS:=node +PKG_NODE_VERSION:=0.12.7 + +PKG_MAINTAINER:=John Crispin +PKG_LICENSE:= + +include $(INCLUDE_DIR)/package.mk + +define Package/node-arduino-firmata + DEPENDS:=+node + SUBMENU:=Node.js + SECTION:=lang + CATEGORY:=Languages + DEPENDS:=+node +node-serialport + TITLE:=Node.js package to access serial ports for reading and writing + URL:=https://www.npmjs.org/package/serialport +endef + +define Package/node-arduino-firmata/description + Node.js package to access serial ports for reading and writing OR Welcome your robotic JavaScript overlords. Better yet, program them! +endef + +define Build/Prepare + /bin/tar xzf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip-components 1 + $(Build/Patch) +endef + +EXTRA_LDFLAGS="-L$(TOOLCHAIN_DIR)/lib/ -Wl,-rpath-link $(TOOLCHAIN_DIR)/lib/" \ + +define Build/Compile + $(MAKE_FLAGS) \ + npm_config_arch=$(CONFIG_ARCH) \ + npm_config_nodedir=$(BUILD_DIR)/node-v$(PKG_NODE_VERSION)/ \ + PREFIX="$(PKG_INSTALL_DIR)/usr/" \ + $(STAGING_DIR_HOST)/bin/npm install -g $(PKG_BUILD_DIR) +endef + +define Package/node-arduino-firmata/install + mkdir -p $(1)/usr/lib/node + $(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/* $(1)/usr/lib/node + rm -rf $(1)/usr/lib/node/arduino-firmata/node_modules/serialport/ + $(CP) -r ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,node-arduino-firmata)) + diff --git a/lang/node-arduino-firmata/files/usr/lib/node/arduino-firmata/lib/arduino-firmata.js b/lang/node-arduino-firmata/files/usr/lib/node/arduino-firmata/lib/arduino-firmata.js new file mode 100644 index 0000000000..578bd402b1 --- /dev/null +++ b/lang/node-arduino-firmata/files/usr/lib/node/arduino-firmata/lib/arduino-firmata.js @@ -0,0 +1,306 @@ +(function() { + 'use strict'; + var ArduinoFirmata, SerialPort, debug, events, exports, serialport, + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + hasProp = {}.hasOwnProperty; + + events = require('eventemitter2'); + + SerialPort = (serialport = require('serialport')).SerialPort; + + debug = require('debug')('arduino-firmata'); + + exports = module.exports = ArduinoFirmata = (function(superClass) { + extend(ArduinoFirmata, superClass); + + ArduinoFirmata.Status = { + CLOSE: 0, + OPEN: 1 + }; + + ArduinoFirmata.INPUT = 0; + + ArduinoFirmata.OUTPUT = 1; + + ArduinoFirmata.ANALOG = 2; + + ArduinoFirmata.PWM = 3; + + ArduinoFirmata.SERVO = 4; + + ArduinoFirmata.SHIFT = 5; + + ArduinoFirmata.I2C = 6; + + ArduinoFirmata.LOW = 0; + + ArduinoFirmata.HIGH = 1; + + ArduinoFirmata.MAX_DATA_BYTES = 32; + + ArduinoFirmata.DIGITAL_MESSAGE = 0x90; + + ArduinoFirmata.ANALOG_MESSAGE = 0xE0; + + ArduinoFirmata.REPORT_ANALOG = 0xC0; + + ArduinoFirmata.REPORT_DIGITAL = 0xD0; + + ArduinoFirmata.SET_PIN_MODE = 0xF4; + + ArduinoFirmata.REPORT_VERSION = 0xF9; + + ArduinoFirmata.SYSTEM_RESET = 0xFF; + + ArduinoFirmata.START_SYSEX = 0xF0; + + ArduinoFirmata.END_SYSEX = 0xF7; + + ArduinoFirmata.list = function(callback) { + return serialport.list(function(err, ports) { + var devices, j, len, port; + if (err) { + return callback(err); + } + devices = []; + for (j = 0, len = ports.length; j < len; j++) { + port = ports[j]; + if (/usb|acm|com\d+/i.test(port.comName)) { + devices.push(port.comName); + } + } + return callback(null, devices); + }); + }; + + function ArduinoFirmata() { + this.status = ArduinoFirmata.Status.CLOSE; + this.wait_for_data = 0; + this.execute_multi_byte_command = 0; + this.multi_byte_channel = 0; + this.stored_input_data = []; + this.parsing_sysex = false; + this.sysex_bytes_read = 0; + this.digital_output_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + this.digital_input_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + this.analog_input_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + this.boardVersion = null; + } + + ArduinoFirmata.prototype.isOldArduinoDevice = function() { + return /usbserial|USB/.test(this.serialport_name); + }; + + ArduinoFirmata.prototype.connect = function(serialport_name, opts) { + this.serialport_name = serialport_name; + if (opts == null) { + opts = { + baudrate: 57600 + }; + } + opts.parser = serialport.parsers.raw; + if (!this.serialport_name) { + ArduinoFirmata.list((function(_this) { + return function(err, devices) { + return _this.connect(devices[0], opts); + }; + })(this)); + return this; + } + this.once('boardReady', function() { + var io_init_wait; + debug('boardReady'); + io_init_wait = this.isOldArduinoDevice() ? (debug("old arduino device found " + this.serialport_name), 3000) : (debug("new arduino device found " + this.serialport_name), 100); + debug("wait " + io_init_wait + "(msec)"); + return setTimeout((function(_this) { + return function() { + var i, j, k; + for (i = j = 0; j < 6; i = ++j) { + _this.write([ArduinoFirmata.REPORT_ANALOG | i, 1]); + } + for (i = k = 0; k < 2; i = ++k) { + _this.write([ArduinoFirmata.REPORT_DIGITAL | i, 1]); + } + debug('init IO ports'); + return _this.emit('connect'); + }; + })(this), io_init_wait); + }); + this.serialport = new SerialPort(this.serialport_name, opts); + this.serialport.once('open', (function(_this) { + return function() { + var cid; + cid = setInterval(function() { + debug('request REPORT_VERSION'); + return _this.write([ArduinoFirmata.REPORT_VERSION]); + }, 500); + _this.once('boardVersion', function(version) { + clearInterval(cid); + _this.status = ArduinoFirmata.Status.OPEN; + return _this.emit('boardReady'); + }); + return _this.serialport.on('data', function(data) { + var byte, j, len, results; + results = []; + for (j = 0, len = data.length; j < len; j++) { + byte = data[j]; + results.push(_this.process_input(byte)); + } + return results; + }); + }; + })(this)); + return this; + }; + + ArduinoFirmata.prototype.isOpen = function() { + return this.status === ArduinoFirmata.Status.OPEN; + }; + + ArduinoFirmata.prototype.close = function(callback) { + this.status = ArduinoFirmata.Status.CLOSE; + return this.serialport.close(callback); + }; + + ArduinoFirmata.prototype.reset = function(callback) { + return this.write([ArduinoFirmata.SYSTEM_RESET], callback); + }; + + ArduinoFirmata.prototype.write = function(bytes, callback) { + return this.serialport.write(bytes, callback); + }; + + ArduinoFirmata.prototype.sysex = function(command, data, callback) { + var write_data; + if (data == null) { + data = []; + } + data = data.map(function(i) { + return i & 0x7f; + }); + write_data = [ArduinoFirmata.START_SYSEX, command].concat(data, [ArduinoFirmata.END_SYSEX]); + return this.write(write_data, callback); + }; + + ArduinoFirmata.prototype.pinMode = function(pin, mode, callback) { + switch (mode) { + case true: + mode = ArduinoFirmata.OUTPUT; + break; + case false: + mode = ArduinoFirmata.INPUT; + } + return this.write([ArduinoFirmata.SET_PIN_MODE, pin, mode], callback); + }; + + ArduinoFirmata.prototype.digitalWrite = function(pin, value, callback) { + var port_num; + this.pinMode(pin, ArduinoFirmata.OUTPUT); + port_num = (pin >>> 3) & 0x0F; + if (value === 0 || value === false) { + this.digital_output_data[port_num] &= ~(1 << (pin & 0x07)); + } else { + this.digital_output_data[port_num] |= 1 << (pin & 0x07); + } + return this.write([ArduinoFirmata.DIGITAL_MESSAGE | port_num, this.digital_output_data[port_num] & 0x7F, this.digital_output_data[port_num] >>> 7], callback); + }; + + ArduinoFirmata.prototype.analogWrite = function(pin, value, callback) { + value = Math.floor(value); + this.pinMode(pin, ArduinoFirmata.PWM); + return this.write([ArduinoFirmata.ANALOG_MESSAGE | (pin & 0x0F), value & 0x7F, value >>> 7], callback); + }; + + ArduinoFirmata.prototype.servoWrite = function(pin, angle, callback) { + this.pinMode(pin, ArduinoFirmata.SERVO); + return this.write([ArduinoFirmata.ANALOG_MESSAGE | (pin & 0x0F), angle & 0x7F, angle >>> 7], callback); + }; + + ArduinoFirmata.prototype.digitalRead = function(pin) { + return ((this.digital_input_data[pin >>> 3] >>> (pin & 0x07)) & 0x01) > 0; + }; + + ArduinoFirmata.prototype.analogRead = function(pin) { + return this.analog_input_data[pin]; + }; + + ArduinoFirmata.prototype.process_input = function(input_data) { + var analog_value, command, diff, i, j, old_analog_value, results, stat, sysex_command, sysex_data; + if (this.parsing_sysex) { + if (input_data === ArduinoFirmata.END_SYSEX) { + this.parsing_sysex = false; + sysex_command = this.stored_input_data[0]; + sysex_data = this.stored_input_data.slice(1, this.sysex_bytes_read); + return this.emit('sysex', { + command: sysex_command, + data: sysex_data + }); + } else { + this.stored_input_data[this.sysex_bytes_read] = input_data; + return this.sysex_bytes_read += 1; + } + } else if (this.wait_for_data > 0 && input_data < 128) { + this.wait_for_data -= 1; + this.stored_input_data[this.wait_for_data] = input_data; + if (this.execute_multi_byte_command !== 0 && this.wait_for_data === 0) { + switch (this.execute_multi_byte_command) { + case ArduinoFirmata.DIGITAL_MESSAGE: + input_data = (this.stored_input_data[0] << 7) + this.stored_input_data[1]; + diff = this.digital_input_data[this.multi_byte_channel] ^ input_data; + this.digital_input_data[this.multi_byte_channel] = input_data; + if (this.listeners('digitalChange').length > 0) { + results = []; + for (i = j = 0; j <= 13; i = ++j) { + if (((0x01 << i) & diff) > 0) { + stat = (input_data & diff) > 0; + results.push(this.emit('digitalChange', { + pin: i + this.multi_byte_channel * 8, + value: stat, + old_value: !stat + })); + } else { + results.push(void 0); + } + } + return results; + } + break; + case ArduinoFirmata.ANALOG_MESSAGE: + analog_value = (this.stored_input_data[0] << 7) + this.stored_input_data[1]; + old_analog_value = this.analogRead(this.multi_byte_channel); + this.analog_input_data[this.multi_byte_channel] = analog_value; + if (old_analog_value !== analog_value) { + return this.emit('analogChange', { + pin: this.multi_byte_channel, + value: analog_value, + old_value: old_analog_value + }); + } + break; + case ArduinoFirmata.REPORT_VERSION: + this.boardVersion = this.stored_input_data[1] + "." + this.stored_input_data[0]; + return this.emit('boardVersion', this.boardVersion); + } + } + } else { + if (input_data < 0xF0) { + command = input_data & 0xF0; + this.multi_byte_channel = input_data & 0x0F; + } else { + command = input_data; + } + if (command === ArduinoFirmata.START_SYSEX) { + this.parsing_sysex = true; + return this.sysex_bytes_read = 0; + } else if (command === ArduinoFirmata.DIGITAL_MESSAGE || command === ArduinoFirmata.ANALOG_MESSAGE || command === ArduinoFirmata.REPORT_VERSION) { + this.wait_for_data = 2; + return this.execute_multi_byte_command = command; + } + } + }; + + return ArduinoFirmata; + + })(events.EventEmitter2); + +}).call(this); diff --git a/lang/node-arduino-firmata/patches/000-new-serialport.patch b/lang/node-arduino-firmata/patches/000-new-serialport.patch new file mode 100644 index 0000000000..10eab64472 --- /dev/null +++ b/lang/node-arduino-firmata/patches/000-new-serialport.patch @@ -0,0 +1,10 @@ +--- a/package.json ++++ b/package.json +@@ -30,7 +30,6 @@ + "author": "Sho Hashimoto ", + "license": "MIT", + "dependencies": { +- "serialport": "*", + "eventemitter2": "*", + "debug": "*" + }, diff --git a/lang/node-cylon/Makefile b/lang/node-cylon/Makefile new file mode 100644 index 0000000000..3f77dcdc90 --- /dev/null +++ b/lang/node-cylon/Makefile @@ -0,0 +1,94 @@ +# +# Copyright (C) 2014 Arduino LLC +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NPM_NAME:=cylon +PKG_NAME:=node-$(PKG_NPM_NAME) +PKG_VERSION:=1.1.0 +PKG_RELEASE:=1 + +PKG_SOURCE:=v0.22.0.tar.gz +PKG_SOURCE_URL:=https://github.com/hybridgroup/cylon-firmata/archive/ + +PKG_BUILD_DEPENDS:=node +PKG_NODE_VERSION:=0.12.7 + +PKG_MAINTAINER:=John Crispin +PKG_LICENSE:=Apache-2.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/node-cylon/default + DEPENDS:=+node $(2) + SUBMENU:=Node.js + SECTION:=lang + CATEGORY:=Languages + TITLE:=CylonJS - $(1) + URL:=https://www.npmjs.org/package/cylon +endef + +define Package/node-cylon + $(call Package/node-cylon/default,Core) +endef + +define Package/node-cylon-i2c + $(call Package/node-cylon/default,I2C,+node-cylon) +endef + +define Package/node-cylon-gpio + $(call Package/node-cylon/default,GPIO,+node-cylon) +endef + +define Package/node-cylon-firmata + $(call Package/node-cylon/default,Firmata,+node-cylon-gpio +node-cylon-i2c +node-arduino-firmata) +endef + +define Package/node-cylon/description + JavaScript Robotics, By Your Command Next generation robotics framework with support for 36 different platforms Get Started +endef + +define Build/Prepare + /bin/tar xzf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip-components 1 + $(Build/Patch) +endef + +EXTRA_LDFLAGS="-L$(TOOLCHAIN_DIR)/lib/ -Wl,-rpath-link $(TOOLCHAIN_DIR)/lib/" \ + +define Build/Compile + $(MAKE_FLAGS) \ + npm_config_arch=$(CONFIG_ARCH) \ + npm_config_nodedir=$(BUILD_DIR)/node-v$(PKG_NODE_VERSION)/ \ + PREFIX="$(PKG_INSTALL_DIR)/usr/" \ + $(STAGING_DIR_HOST)/bin/npm install -g $(PKG_BUILD_DIR) +endef + +define Package/node-cylon/install + mkdir -p $(1)/usr/lib/node/cylon + $(CP) -r $(PKG_INSTALL_DIR)/usr/lib/node_modules/cylon-firmata/node_modules/cylon/* $(1)/usr/lib/node/cylon/ +endef + +define Package/node-cylon-i2c/install + mkdir -p $(1)/usr/lib/node/cylon-i2c + $(CP) -r $(PKG_INSTALL_DIR)/usr/lib/node_modules/cylon-firmata/node_modules/cylon-i2c/* $(1)/usr/lib/node/cylon-i2c/ +endef + +define Package/node-cylon-gpio/install + mkdir -p $(1)/usr/lib/node/cylon-gpio + $(CP) -r $(PKG_INSTALL_DIR)/usr/lib/node_modules/cylon-firmata/node_modules/cylon-gpio/* $(1)/usr/lib/node/cylon-gpio/ +endef + +define Package/node-cylon-firmata/install + mkdir -p $(1)/usr/lib/node/cylon-firmata + $(CP) -r $(PKG_INSTALL_DIR)/usr/lib/node_modules/cylon-firmata/{index.js,lib,LICENSE,package.json,README.md,RELEASES.md,spec} $(1)/usr/lib/node/cylon-firmata/ +endef + +$(eval $(call BuildPackage,node-cylon)) +$(eval $(call BuildPackage,node-cylon-i2c)) +$(eval $(call BuildPackage,node-cylon-gpio)) +$(eval $(call BuildPackage,node-cylon-firmata)) + diff --git a/lang/node-hid/Makefile b/lang/node-hid/Makefile new file mode 100644 index 0000000000..4485355134 --- /dev/null +++ b/lang/node-hid/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NPM_NAME:=hid +PKG_NAME:=node-$(PKG_NPM_NAME) +PKG_VERSION:=0.4.0 + +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/node-hid/node-hid.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=c56c8aa5d113c6f2574d1f7e64d41745702965bb +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz + +PKG_BUILD_DEPENDS:=node +PKG_NODE_VERSION:=0.12.7 + +PKG_MAINTAINER:=John Crispin +PKG_LICENSE:=MIT + +include $(INCLUDE_DIR)/package.mk + +define Package/node-hid + DEPENDS:=+node + SUBMENU:=Node.js + SECTION:=lang + CATEGORY:=Languages + DEPENDS:=+libusb-1.0 +hidapi +libstdcpp + TITLE:=Node.js package to access HID devices + URL:=https://github.com/node-hid/node-hid +endef + +define Package/node-hid/description + Node.js package to access HID devices +endef + +EXTRA_LDFLAGS+="-lhidapi-libusb" +EXTRA_CFLAGS+="-I$(STAGING_DIR)/usr/include/hidapi/" + +define Build/Compile + $(MAKE_VARS) \ + $(MAKE_FLAGS) \ + npm_config_arch=$(CONFIG_ARCH) \ + npm_config_nodedir=$(BUILD_DIR)/node-v$(PKG_NODE_VERSION)/ \ + PREFIX="$(PKG_INSTALL_DIR)/usr/" \ + $(STAGING_DIR_HOST)/bin/npm install -g $(PKG_BUILD_DIR) +endef + +define Package/node-hid/install + mkdir -p $(1)/usr/lib/node/node-hid/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/node-hid/{index.js,package.json,build,node_modules} $(1)/usr/lib/node/node-hid/ +endef + +$(eval $(call BuildPackage,node-hid)) + diff --git a/lang/node-hid/patches/000-compile.patch b/lang/node-hid/patches/000-compile.patch new file mode 100644 index 0000000000..d44e9b30f4 --- /dev/null +++ b/lang/node-hid/patches/000-compile.patch @@ -0,0 +1,2457 @@ +--- a/package.json ++++ b/package.json +@@ -14,9 +14,6 @@ + "type": "git", + "url": "git://github.com/hanshuebner/node-hid.git" + }, +- "scripts": { +- "prepublish": "git submodule update --init" +- }, + "main": "./index.js", + "engines": { + "node": ">=0.8.0" +--- a/src/wscript ++++ b/src/wscript +@@ -3,10 +3,8 @@ + import sys; + import os; + +-hidapi_home='../hidapi' + + cflags=["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall", "-fPIC" ] +-includes=[ hidapi_home + "/hidapi" ] + + def set_options(opt): + opt.tool_options("compiler_cxx") +@@ -16,24 +14,10 @@ + conf.check_tool("compiler_cxx") + conf.check_tool("node_addon") + conf.check_tool("compiler_cc") +- if sys.platform == 'darwin': +- conf.env.append_value('LINKFLAGS', ['Release/libhidapi.a', '-framework', 'IOKit', '-framework', 'CoreFoundation']) +- else: +- conf.env.append_value('LINKFLAGS', ['Release/libhidapi.a', '-ludev' ]) +- +-def build(bld): +- bld.add_group("hidapi") +- hidapi = bld.new_task_gen("cc", "staticlib") +- hidapi.includes = includes +- hidapi.cflags = cflags +- if sys.platform == 'darwin': +- hidapi.source = "../hidapi/mac/hid.c" +- else: +- hidapi.source = "../hidapi/linux/hid.c" +- hidapi.target = "hidapi" + ++def build(bld): + bld.add_group("adapter") +- adapter = bld.new_task_gen("cxx", "shlib", "node_addon", use = ['hidapi']) ++ adapter = bld.new_task_gen("cxx", "shlib", "node_addon") + adapter.includes = includes + adapter.cxxflags = cflags + adapter.target = "HID" +--- a/binding.gyp ++++ b/binding.gyp +@@ -4,61 +4,8 @@ + }, + 'targets': [ + { +- 'target_name': 'hidapi', +- 'type': 'static_library', +- 'conditions': [ +- [ 'OS=="mac"', { +- 'sources': [ 'hidapi/mac/hid.c' ], +- 'include_dirs+': [ +- '/usr/include/libusb-1.0/' +- ] +- }], +- [ 'OS=="linux"', { +- 'conditions': [ +- [ 'driver=="libusb"', { +- 'sources': [ 'hidapi/libusb/hid.c' ], +- 'include_dirs+': [ +- '/usr/include/libusb-1.0/' +- ] +- }], +- [ 'driver=="hidraw"', { +- 'sources': [ 'hidapi/linux/hid.c' ] +- }] +- ] +- }], +- [ 'OS=="win"', { +- 'sources': [ 'hidapi/windows/hid.c' ], +- 'msvs_settings': { +- 'VCLinkerTool': { +- 'AdditionalDependencies': [ +- 'setupapi.lib', +- ] +- } +- } +- }] +- ], +- 'direct_dependent_settings': { +- 'include_dirs': [ +- 'hidapi/hidapi', +- " ++ * - Benjamin Byholm ++ * - Trevor Norris ++ * - Nathan Rajlich ++ * - Brett Lawson ++ * - Ben Noordhuis ++ * ++ * MIT +no-false-attribs License ++ * ++ * Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 ++ * ++ * See https://github.com/rvagg/nan for the latest update to this file ++ **********************************************************************************/ ++ ++#ifndef NAN_H_ ++#define NAN_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(__GNUC__) && !defined(DEBUG) ++# define NAN_INLINE inline __attribute__((always_inline)) ++#elif defined(_MSC_VER) && !defined(DEBUG) ++# define NAN_INLINE __forceinline ++#else ++# define NAN_INLINE inline ++#endif ++ ++#if defined(__GNUC__) && !V8_DISABLE_DEPRECATIONS ++# define NAN_DEPRECATED __attribute__((deprecated)) ++#elif defined(_MSC_VER) && !V8_DISABLE_DEPRECATIONS ++# define NAN_DEPRECATED __declspec(deprecated) ++#else ++# define NAN_DEPRECATED ++#endif ++ ++// some generic helpers ++ ++template NAN_INLINE bool NanSetPointerSafe( ++ T *var ++ , T val ++) { ++ if (var) { ++ *var = val; ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++template NAN_INLINE T NanGetPointerSafe( ++ T *var ++ , T fallback = reinterpret_cast(0) ++) { ++ if (var) { ++ return *var; ++ } else { ++ return fallback; ++ } ++} ++ ++NAN_INLINE bool NanBooleanOptionValue( ++ v8::Local optionsObj ++ , v8::Handle opt, bool def ++) { ++ if (def) { ++ return optionsObj.IsEmpty() ++ || !optionsObj->Has(opt) ++ || optionsObj->Get(opt)->BooleanValue(); ++ } else { ++ return !optionsObj.IsEmpty() ++ && optionsObj->Has(opt) ++ && optionsObj->Get(opt)->BooleanValue(); ++ } ++} ++ ++NAN_INLINE bool NanBooleanOptionValue( ++ v8::Local optionsObj ++ , v8::Handle opt ++) { ++ return NanBooleanOptionValue(optionsObj, opt, false); ++} ++ ++NAN_INLINE uint32_t NanUInt32OptionValue( ++ v8::Local optionsObj ++ , v8::Handle opt ++ , uint32_t def ++) { ++ return !optionsObj.IsEmpty() ++ && optionsObj->Has(opt) ++ && optionsObj->Get(opt)->IsNumber() ++ ? optionsObj->Get(opt)->Uint32Value() ++ : def; ++} ++ ++#if (NODE_MODULE_VERSION > 0x000B) ++// Node 0.11+ (0.11.3 and below won't compile with these) ++ ++# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo& ++# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args ++# define _NAN_METHOD_RETURN_TYPE void ++ ++# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo& ++# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args ++# define _NAN_GETTER_RETURN_TYPE void ++ ++# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo& ++# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args ++# define _NAN_SETTER_RETURN_TYPE void ++ ++# define _NAN_PROPERTY_GETTER_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args ++# define _NAN_PROPERTY_GETTER_RETURN_TYPE void ++ ++# define _NAN_PROPERTY_SETTER_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args ++# define _NAN_PROPERTY_SETTER_RETURN_TYPE void ++ ++# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args ++# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void ++ ++# define _NAN_PROPERTY_DELETER_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_PROPERTY_DELETER_ARGS \ ++ _NAN_PROPERTY_DELETER_ARGS_TYPE args ++# define _NAN_PROPERTY_DELETER_RETURN_TYPE void ++ ++# define _NAN_PROPERTY_QUERY_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args ++# define _NAN_PROPERTY_QUERY_RETURN_TYPE void ++ ++# define _NAN_INDEX_GETTER_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args ++# define _NAN_INDEX_GETTER_RETURN_TYPE void ++ ++# define _NAN_INDEX_SETTER_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args ++# define _NAN_INDEX_SETTER_RETURN_TYPE void ++ ++# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args ++# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void ++ ++# define _NAN_INDEX_DELETER_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args ++# define _NAN_INDEX_DELETER_RETURN_TYPE void ++ ++# define _NAN_INDEX_QUERY_ARGS_TYPE \ ++ const v8::PropertyCallbackInfo& ++# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args ++# define _NAN_INDEX_QUERY_RETURN_TYPE void ++ ++ typedef v8::FunctionCallback NanFunctionCallback; ++ ++ template ++ NAN_INLINE v8::Local NanNew() { ++ return T::New(v8::Isolate::GetCurrent()); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew(P arg1) { ++ return T::New(v8::Isolate::GetCurrent(), arg1); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Handle receiver ++ , int argc ++ , v8::Handle argv[] = 0) { ++ return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ NanFunctionCallback callback ++ , v8::Handle data = v8::Handle() ++ , v8::Handle signature = v8::Handle()) { ++ return T::New(v8::Isolate::GetCurrent(), callback, data, signature); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew(v8::Handle arg1) { ++ return v8::Local::New(v8::Isolate::GetCurrent(), arg1); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew(const v8::Persistent &arg1) { ++ return v8::Local::New(v8::Isolate::GetCurrent(), arg1); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew(P arg1, int arg2) { ++ return T::New(v8::Isolate::GetCurrent(), arg1, arg2); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew() { ++ return v8::Array::New(v8::Isolate::GetCurrent()); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(int length) { ++ return v8::Array::New(v8::Isolate::GetCurrent(), length); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(double time) { ++ return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(int time) { ++ return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); ++ } ++ ++ typedef v8::UnboundScript NanUnboundScript; ++ typedef v8::Script NanBoundScript; ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ P s ++ , const v8::ScriptOrigin& origin ++ ) { ++ v8::ScriptCompiler::Source source(s, origin); ++ return v8::ScriptCompiler::CompileUnbound( ++ v8::Isolate::GetCurrent(), &source); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ v8::Local s ++ ) { ++ v8::ScriptCompiler::Source source(s); ++ return v8::ScriptCompiler::CompileUnbound( ++ v8::Isolate::GetCurrent(), &source); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(bool value) { ++ return v8::BooleanObject::New(value).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local ++ NanNew >( ++ v8::Local value) { ++ return v8::StringObject::New(value).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local ++ NanNew >( ++ v8::Handle value) { ++ return v8::StringObject::New(value).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(double val) { ++ return v8::NumberObject::New( ++ v8::Isolate::GetCurrent(), val).As(); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Handle pattern, v8::RegExp::Flags flags) { ++ return v8::RegExp::New(pattern, flags); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Local pattern, v8::RegExp::Flags flags) { ++ return v8::RegExp::New(pattern, flags); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Handle pattern, v8::RegExp::Flags flags) { ++ return v8::RegExp::New(pattern, flags); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Local pattern, v8::RegExp::Flags flags) { ++ return v8::RegExp::New(pattern, flags); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(int32_t val) { ++ return v8::Uint32::NewFromUnsigned( ++ v8::Isolate::GetCurrent(), val)->ToUint32(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(uint32_t val) { ++ return v8::Uint32::NewFromUnsigned( ++ v8::Isolate::GetCurrent(), val)->ToUint32(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(int32_t val) { ++ return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(uint32_t val) { ++ return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ char *arg ++ , int length) { ++ return v8::String::NewFromUtf8( ++ v8::Isolate::GetCurrent() ++ , arg ++ , v8::String::kNormalString ++ , length); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ const char *arg ++ , int length) { ++ return v8::String::NewFromUtf8( ++ v8::Isolate::GetCurrent() ++ , arg ++ , v8::String::kNormalString ++ , length); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(char *arg) { ++ return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ const char *arg) { ++ return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ uint8_t *arg ++ , int length) { ++ return v8::String::NewFromOneByte( ++ v8::Isolate::GetCurrent() ++ , arg ++ , v8::String::kNormalString ++ , length); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ const uint8_t *arg ++ , int length) { ++ return v8::String::NewFromOneByte( ++ v8::Isolate::GetCurrent() ++ , arg ++ , v8::String::kNormalString ++ , length); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(uint8_t *arg) { ++ return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ const uint8_t *arg) { ++ return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ uint16_t *arg ++ , int length) { ++ return v8::String::NewFromTwoByte( ++ v8::Isolate::GetCurrent() ++ , arg ++ , v8::String::kNormalString ++ , length); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ const uint16_t *arg ++ , int length) { ++ return v8::String::NewFromTwoByte( ++ v8::Isolate::GetCurrent() ++ , arg ++ , v8::String::kNormalString ++ , length); ++ } ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ uint16_t *arg) { ++ return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ const uint16_t *arg) { ++ return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ std::string arg) { ++ return NanNew(arg.c_str(), arg.size()); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew() { ++ return v8::String::Empty(v8::Isolate::GetCurrent()); ++ } ++ ++ NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { ++ return NanNew(arg, length); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ const uint8_t* arg ++ , int length = -1) { ++ return NanNew(arg, length); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ const uint16_t* arg ++ , int length = -1) { ++ return NanNew(arg, length); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ const std::string& arg) { ++ return NanNew(arg.c_str(), arg.size()); ++ } ++ ++ NAN_INLINE v8::Local NanNew(double val) { ++ return NanNew(val); ++ } ++ ++ NAN_INLINE v8::Local NanNew(int val) { ++ return NanNew(val); ++ } ++ ++ NAN_INLINE v8::Local NanNew(unsigned int val) { ++ return NanNew(val); ++ } ++ ++ NAN_INLINE v8::Local NanNew(bool val) { ++ return NanNew(val); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ v8::String::ExternalStringResource *resource) { ++ return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ v8::String::ExternalAsciiStringResource *resource) { ++ return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); ++ } ++ ++# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent()) ++# define NanEscapableScope() \ ++ v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()) ++ ++ template ++ NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Handle val) { ++ return NanNew(val); ++ } ++ ++ template ++ NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Local val) { ++ return val; ++ } ++ ++# define NanEscapeScope(val) scope.Escape(_NanEscapeScopeHelper(val)) ++# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent()) ++# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent()) ++# define NanReturnValue(value) return args.GetReturnValue().Set(value) ++# define NanReturnUndefined() return ++# define NanReturnNull() return args.GetReturnValue().SetNull() ++# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString() ++ ++# define NanObjectWrapHandle(obj) obj->handle() ++ ++ NAN_INLINE v8::Local NanUndefined() { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent()))); ++ } ++ ++ NAN_INLINE v8::Local NanNull() { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent()))); ++ } ++ ++ NAN_INLINE v8::Local NanTrue() { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent()))); ++ } ++ ++ NAN_INLINE v8::Local NanFalse() { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent()))); ++ } ++ ++ NAN_INLINE int NanAdjustExternalMemory(int bc) { ++ return static_cast( ++ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc)); ++ } ++ ++ NAN_INLINE void NanSetTemplate( ++ v8::Handle templ ++ , const char *name ++ , v8::Handle value) { ++ templ->Set(v8::Isolate::GetCurrent(), name, value); ++ } ++ ++ NAN_INLINE void NanSetTemplate( ++ v8::Handle templ ++ , v8::Handle name ++ , v8::Handle value ++ , v8::PropertyAttribute attributes) { ++ templ->Set(name, value, attributes); ++ } ++ ++ NAN_INLINE v8::Local NanGetCurrentContext() { ++ return v8::Isolate::GetCurrent()->GetCurrentContext(); ++ } ++ ++ NAN_INLINE void* NanGetInternalFieldPointer( ++ v8::Handle object ++ , int index) { ++ return object->GetAlignedPointerFromInternalField(index); ++ } ++ ++ NAN_INLINE void NanSetInternalFieldPointer( ++ v8::Handle object ++ , int index ++ , void* value) { ++ object->SetAlignedPointerInInternalField(index, value); ++ } ++ ++ NAN_INLINE void NanAddGCEpilogueCallback( ++ v8::Isolate::GCEpilogueCallback callback ++ , v8::GCType gc_type_filter = v8::kGCTypeAll) { ++ v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); ++ } ++ ++ NAN_INLINE void NanRemoveGCEpilogueCallback( ++ v8::Isolate::GCEpilogueCallback callback) { ++ v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); ++ } ++ ++ NAN_INLINE void NanAddGCPrologueCallback( ++ v8::Isolate::GCPrologueCallback callback ++ , v8::GCType gc_type_filter = v8::kGCTypeAll) { ++ v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); ++ } ++ ++ NAN_INLINE void NanRemoveGCPrologueCallback( ++ v8::Isolate::GCPrologueCallback callback) { ++ v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); ++ } ++ ++ NAN_INLINE void NanGetHeapStatistics( ++ v8::HeapStatistics *heap_statistics) { ++ v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); ++ } ++ ++ NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( ++ const char* data, int length = -1) { ++ return NanNew(data, length); ++ } ++ ++ template ++ NAN_INLINE void NanAssignPersistent( ++ v8::Persistent& handle ++ , v8::Handle obj) { ++ handle.Reset(v8::Isolate::GetCurrent(), obj); ++ } ++ ++ template ++ NAN_INLINE void NanAssignPersistent( ++ v8::Persistent& handle ++ , const v8::Persistent& obj) { ++ handle.Reset(v8::Isolate::GetCurrent(), obj); ++ } ++ ++ template ++ class _NanWeakCallbackData; ++ ++ template ++ struct _NanWeakCallbackInfo { ++ typedef void (*Callback)(const _NanWeakCallbackData& data); ++ NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) ++ : parameter(param), callback(cb) { ++ NanAssignPersistent(persistent, handle); ++ } ++ ++ NAN_INLINE ~_NanWeakCallbackInfo() { ++ persistent.Reset(); ++ } ++ ++ P* const parameter; ++ Callback const callback; ++ v8::Persistent persistent; ++ }; ++ ++ template ++ class _NanWeakCallbackData { ++ public: ++ NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) ++ : info_(info) { } ++ ++ NAN_INLINE v8::Local GetValue() const { ++ return NanNew(info_->persistent); ++ } ++ ++ NAN_INLINE P* GetParameter() const { return info_->parameter; } ++ ++ NAN_INLINE bool IsNearDeath() const { ++ return info_->persistent.IsNearDeath(); ++ } ++ ++ NAN_INLINE void Revive() const; ++ ++ NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { ++ return info_; ++ } ++ ++ NAN_DEPRECATED NAN_INLINE void Dispose() const { ++ } ++ ++ private: ++ _NanWeakCallbackInfo* info_; ++ }; ++ ++ template ++ static void _NanWeakCallbackDispatcher( ++ const v8::WeakCallbackData > &data) { ++ _NanWeakCallbackInfo *info = data.GetParameter(); ++ _NanWeakCallbackData wcbd(info); ++ info->callback(wcbd); ++ if (wcbd.IsNearDeath()) { ++ delete wcbd.GetCallbackInfo(); ++ } ++ } ++ ++ template ++ NAN_INLINE void _NanWeakCallbackData::Revive() const { ++ info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher); ++ } ++ ++template ++NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( ++ v8::Handle handle ++ , P* parameter ++ , typename _NanWeakCallbackInfo::Callback callback) { ++ _NanWeakCallbackInfo *cbinfo = ++ new _NanWeakCallbackInfo(handle, parameter, callback); ++ cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher); ++ return cbinfo; ++} ++ ++# define NAN_WEAK_CALLBACK(name) \ ++ template \ ++ static void name(const _NanWeakCallbackData &data) ++ ++# define _NAN_ERROR(fun, errmsg) fun(NanNew(errmsg)) ++ ++# define _NAN_THROW_ERROR(fun, errmsg) \ ++ do { \ ++ NanScope(); \ ++ v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg)); \ ++ } while (0); ++ ++ NAN_INLINE v8::Local NanError(const char* errmsg) { ++ return _NAN_ERROR(v8::Exception::Error, errmsg); ++ } ++ ++ NAN_INLINE void NanThrowError(const char* errmsg) { ++ _NAN_THROW_ERROR(v8::Exception::Error, errmsg); ++ } ++ ++ NAN_INLINE void NanThrowError(v8::Handle error) { ++ NanScope(); ++ v8::Isolate::GetCurrent()->ThrowException(error); ++ } ++ ++ NAN_INLINE v8::Local NanError( ++ const char *msg ++ , const int errorNumber ++ ) { ++ v8::Local err = v8::Exception::Error(NanNew(msg)); ++ v8::Local obj = err.As(); ++ obj->Set(NanNew("code"), NanNew(errorNumber)); ++ return err; ++ } ++ ++ NAN_INLINE void NanThrowError( ++ const char *msg ++ , const int errorNumber ++ ) { ++ NanThrowError(NanError(msg, errorNumber)); ++ } ++ ++ NAN_INLINE v8::Local NanTypeError(const char* errmsg) { ++ return _NAN_ERROR(v8::Exception::TypeError, errmsg); ++ } ++ ++ NAN_INLINE void NanThrowTypeError(const char* errmsg) { ++ _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); ++ } ++ ++ NAN_INLINE v8::Local NanRangeError(const char* errmsg) { ++ return _NAN_ERROR(v8::Exception::RangeError, errmsg); ++ } ++ ++ NAN_INLINE void NanThrowRangeError(const char* errmsg) { ++ _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); ++ } ++ ++ template NAN_INLINE void NanDisposePersistent( ++ v8::Persistent &handle ++ ) { ++ handle.Reset(); ++ } ++ ++ NAN_INLINE v8::Local NanNewBufferHandle ( ++ char *data ++ , size_t length ++ , node::smalloc::FreeCallback callback ++ , void *hint ++ ) { ++ return node::Buffer::New( ++ v8::Isolate::GetCurrent(), data, length, callback, hint); ++ } ++ ++ NAN_INLINE v8::Local NanNewBufferHandle ( ++ const char *data ++ , uint32_t size ++ ) { ++ return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); ++ } ++ ++ NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { ++ return node::Buffer::New(v8::Isolate::GetCurrent(), size); ++ } ++ ++ NAN_INLINE v8::Local NanBufferUse( ++ char* data ++ , uint32_t size ++ ) { ++ return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); ++ } ++ ++ NAN_INLINE bool NanHasInstance( ++ v8::Persistent& function_template ++ , v8::Handle value ++ ) { ++ return NanNew(function_template)->HasInstance(value); ++ } ++ ++ NAN_INLINE v8::Local NanNewContextHandle( ++ v8::ExtensionConfiguration* extensions = NULL ++ , v8::Handle tmpl = v8::Handle() ++ , v8::Handle obj = v8::Handle() ++ ) { ++ v8::Isolate* isolate = v8::Isolate::GetCurrent(); ++ return v8::Local::New( ++ isolate ++ , v8::Context::New(isolate, extensions, tmpl, obj) ++ ); ++ } ++ ++ NAN_INLINE v8::Local NanCompileScript( ++ v8::Local s ++ , const v8::ScriptOrigin& origin ++ ) { ++ v8::ScriptCompiler::Source source(s, origin); ++ return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); ++ } ++ ++ NAN_INLINE v8::Local NanCompileScript( ++ v8::Local s ++ ) { ++ v8::ScriptCompiler::Source source(s); ++ return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); ++ } ++ ++ NAN_INLINE v8::Local NanRunScript( ++ v8::Handle script ++ ) { ++ return script->BindToCurrentContext()->Run(); ++ } ++ ++ NAN_INLINE v8::Local NanRunScript( ++ v8::Handle script ++ ) { ++ return script->Run(); ++ } ++ ++ NAN_INLINE v8::Local NanMakeCallback( ++ v8::Handle target ++ , v8::Handle func ++ , int argc ++ , v8::Handle* argv) { ++ return NanNew(node::MakeCallback( ++ v8::Isolate::GetCurrent(), target, func, argc, argv)); ++ } ++ ++ NAN_INLINE v8::Local NanMakeCallback( ++ v8::Handle target ++ , v8::Handle symbol ++ , int argc ++ , v8::Handle* argv) { ++ return NanNew(node::MakeCallback( ++ v8::Isolate::GetCurrent(), target, symbol, argc, argv)); ++ } ++ ++ NAN_INLINE v8::Local NanMakeCallback( ++ v8::Handle target ++ , const char* method ++ , int argc ++ , v8::Handle* argv) { ++ return NanNew(node::MakeCallback( ++ v8::Isolate::GetCurrent(), target, method, argc, argv)); ++ } ++ ++ template ++ NAN_INLINE void NanSetIsolateData( ++ v8::Isolate *isolate ++ , T *data ++ ) { ++ isolate->SetData(0, data); ++ } ++ ++ template ++ NAN_INLINE T *NanGetIsolateData( ++ v8::Isolate *isolate ++ ) { ++ return static_cast(isolate->GetData(0)); ++ } ++ ++ class NanAsciiString { ++ public: ++ NAN_INLINE explicit NanAsciiString(v8::Handle from) { ++ v8::Local toStr = from->ToString(); ++ int buf_size = toStr->Length() + 1; ++ buf = new char[buf_size]; ++ size = toStr->WriteOneByte( ++ reinterpret_cast(buf), 0, buf_size); ++ } ++ ++ NAN_INLINE int Size() const { ++ return size; ++ } ++ ++ NAN_INLINE char* operator*() { return buf; } ++ ++ NAN_INLINE ~NanAsciiString() { ++ delete[] buf; ++ } ++ ++ private: ++ char *buf; ++ int size; ++ }; ++ ++ class NanUtf8String { ++ public: ++ NAN_INLINE explicit NanUtf8String(v8::Handle from) { ++ v8::Local toStr = from->ToString(); ++ int buf_size = toStr->Utf8Length() + 1; ++ buf = new char[buf_size]; ++ size = toStr->WriteUtf8(buf, buf_size); ++ } ++ ++ NAN_INLINE int Size() const { ++ return size; ++ } ++ ++ NAN_INLINE char* operator*() { return buf; } ++ ++ NAN_INLINE ~NanUtf8String() { ++ delete[] buf; ++ } ++ ++ private: ++ char *buf; ++ int size; ++ }; ++ ++ class NanUcs2String { ++ public: ++ NAN_INLINE explicit NanUcs2String(v8::Handle from) { ++ v8::Local toStr = from->ToString(); ++ int buf_size = toStr->Length() + 1; ++ buf = new uint16_t[buf_size]; ++ size = toStr->Write(buf, 0, buf_size); ++ } ++ ++ NAN_INLINE int Size() const { ++ return size; ++ } ++ ++ NAN_INLINE uint16_t* operator*() { return buf; } ++ ++ NAN_INLINE ~NanUcs2String() { ++ delete[] buf; ++ } ++ ++ private: ++ uint16_t *buf; ++ int size; ++ }; ++ ++#else ++// Node 0.8 and 0.10 ++ ++# define _NAN_METHOD_ARGS_TYPE const v8::Arguments& ++# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args ++# define _NAN_METHOD_RETURN_TYPE v8::Handle ++ ++# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo & ++# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args ++# define _NAN_GETTER_RETURN_TYPE v8::Handle ++ ++# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo & ++# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args ++# define _NAN_SETTER_RETURN_TYPE void ++ ++# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args ++# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle ++ ++# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args ++# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle ++ ++# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args ++# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle ++ ++# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args ++# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle ++ ++# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args ++# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle ++ ++# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args ++# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle ++ ++# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args ++# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle ++ ++# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args ++# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle ++ ++# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args ++# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle ++ ++# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo& ++# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args ++# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle ++ ++ typedef v8::InvocationCallback NanFunctionCallback; ++ ++ NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( ++ const char* data, int length = -1) { ++ return v8::String::NewSymbol(data, length); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew() { ++ return v8::Local::New(T::New()); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew(v8::Handle arg) { ++ return v8::Local::New(arg); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Handle receiver ++ , int argc ++ , v8::Handle argv[] = 0) { ++ return v8::Signature::New(receiver, argc, argv); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ NanFunctionCallback callback ++ , v8::Handle data = v8::Handle() ++ , v8::Handle signature = v8::Handle()) { ++ return T::New(callback, data, signature); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew(const v8::Persistent &arg) { ++ return v8::Local::New(arg); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew(P arg) { ++ return v8::Local::New(T::New(arg)); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew(P arg, int length) { ++ return v8::Local::New(T::New(arg, length)); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Handle pattern, v8::RegExp::Flags flags) { ++ return v8::RegExp::New(pattern, flags); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Local pattern, v8::RegExp::Flags flags) { ++ return v8::RegExp::New(pattern, flags); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Handle pattern, v8::RegExp::Flags flags) { ++ return v8::RegExp::New(pattern, flags); ++ } ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ v8::Local pattern, v8::RegExp::Flags flags) { ++ return v8::RegExp::New(pattern, flags); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew() { ++ return v8::Array::New(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(int length) { ++ return v8::Array::New(length); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(double time) { ++ return v8::Date::New(time).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(int time) { ++ return v8::Date::New(time).As(); ++ } ++ ++ typedef v8::Script NanUnboundScript; ++ typedef v8::Script NanBoundScript; ++ ++ template ++ NAN_INLINE v8::Local NanNew( ++ P s ++ , const v8::ScriptOrigin& origin ++ ) { ++ return v8::Script::New(s, const_cast(&origin)); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ v8::Local s ++ ) { ++ return v8::Script::New(s); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(bool value) { ++ return v8::BooleanObject::New(value).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local ++ NanNew >( ++ v8::Local value) { ++ return v8::StringObject::New(value).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local ++ NanNew >( ++ v8::Handle value) { ++ return v8::StringObject::New(value).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(double val) { ++ return v8::NumberObject::New(val).As(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(int32_t val) { ++ return v8::Uint32::NewFromUnsigned(val)->ToUint32(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(uint32_t val) { ++ return v8::Uint32::NewFromUnsigned(val)->ToUint32(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(int32_t val) { ++ return v8::Int32::New(val)->ToInt32(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(uint32_t val) { ++ return v8::Int32::New(val)->ToInt32(); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ uint8_t *arg ++ , int length) { ++ int len = length; ++ if (len < 0) { ++ size_t temp = strlen(reinterpret_cast(arg)); ++ assert(temp <= INT_MAX && "too long string"); ++ len = static_cast(temp); ++ } ++ uint16_t *warg = new uint16_t[len]; ++ for (int i = 0; i < len; i++) { ++ warg[i] = arg[i]; ++ } ++ v8::Local retval = v8::String::New(warg, len); ++ delete[] warg; ++ return retval; ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ const uint8_t *arg ++ , int length) { ++ int len = length; ++ if (len < 0) { ++ size_t temp = strlen(reinterpret_cast(arg)); ++ assert(temp <= INT_MAX && "too long string"); ++ len = static_cast(temp); ++ } ++ uint16_t *warg = new uint16_t[len]; ++ for (int i = 0; i < len; i++) { ++ warg[i] = arg[i]; ++ } ++ v8::Local retval = v8::String::New(warg, len); ++ delete[] warg; ++ return retval; ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew(uint8_t *arg) { ++ size_t temp = strlen(reinterpret_cast(arg)); ++ assert(temp <= INT_MAX && "too long string"); ++ int length = static_cast(temp); ++ uint16_t *warg = new uint16_t[length]; ++ for (int i = 0; i < length; i++) { ++ warg[i] = arg[i]; ++ } ++ ++ v8::Local retval = v8::String::New(warg, length); ++ delete[] warg; ++ return retval; ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ const uint8_t *arg) { ++ size_t temp = strlen(reinterpret_cast(arg)); ++ assert(temp <= INT_MAX && "too long string"); ++ int length = static_cast(temp); ++ uint16_t *warg = new uint16_t[length]; ++ for (int i = 0; i < length; i++) { ++ warg[i] = arg[i]; ++ } ++ v8::Local retval = v8::String::New(warg, length); ++ delete[] warg; ++ return retval; ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew( ++ std::string arg) { ++ return NanNew(arg.c_str(), arg.size()); ++ } ++ ++ template<> ++ NAN_INLINE v8::Local NanNew() { ++ return v8::String::Empty(); ++ } ++ ++ NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { ++ return NanNew(arg, length); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ const uint8_t* arg ++ , int length = -1) { ++ return NanNew(arg, length); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ const uint16_t* arg ++ , int length = -1) { ++ return NanNew(arg, length); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ std::string& arg) { ++ return NanNew(arg.c_str(), arg.size()); ++ } ++ ++ NAN_INLINE v8::Local NanNew(double val) { ++ return NanNew(val); ++ } ++ ++ NAN_INLINE v8::Local NanNew(int val) { ++ return NanNew(val); ++ } ++ ++ NAN_INLINE v8::Local NanNew(unsigned int val) { ++ return NanNew(val); ++ } ++ ++ NAN_INLINE v8::Local NanNew(bool val) { ++ return NanNew(val); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ v8::String::ExternalStringResource *resource) { ++ return v8::String::NewExternal(resource); ++ } ++ ++ NAN_INLINE v8::Local NanNew( ++ v8::String::ExternalAsciiStringResource *resource) { ++ return v8::String::NewExternal(resource); ++ } ++ ++# define NanScope() v8::HandleScope scope ++# define NanEscapableScope() v8::HandleScope scope ++# define NanEscapeScope(val) scope.Close(val) ++# define NanLocker() v8::Locker locker ++# define NanUnlocker() v8::Unlocker unlocker ++# define NanReturnValue(value) return scope.Close(value) ++# define NanReturnUndefined() return v8::Undefined() ++# define NanReturnNull() return v8::Null() ++# define NanReturnEmptyString() return v8::String::Empty() ++# define NanObjectWrapHandle(obj) v8::Local::New(obj->handle_) ++ ++ NAN_INLINE v8::Local NanUndefined() { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(v8::Undefined())); ++ } ++ ++ NAN_INLINE v8::Local NanNull() { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(v8::Null())); ++ } ++ ++ NAN_INLINE v8::Local NanTrue() { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(v8::True())); ++ } ++ ++ NAN_INLINE v8::Local NanFalse() { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(v8::False())); ++ } ++ ++ NAN_INLINE int NanAdjustExternalMemory(int bc) { ++ return static_cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc)); ++ } ++ ++ NAN_INLINE void NanSetTemplate( ++ v8::Handle templ ++ , const char *name ++ , v8::Handle value) { ++ templ->Set(name, value); ++ } ++ ++ NAN_INLINE void NanSetTemplate( ++ v8::Handle templ ++ , v8::Handle name ++ , v8::Handle value ++ , v8::PropertyAttribute attributes) { ++ templ->Set(name, value, attributes); ++ } ++ ++ NAN_INLINE v8::Local NanGetCurrentContext() { ++ return v8::Context::GetCurrent(); ++ } ++ ++ NAN_INLINE void* NanGetInternalFieldPointer( ++ v8::Handle object ++ , int index) { ++ return object->GetPointerFromInternalField(index); ++ } ++ ++ NAN_INLINE void NanSetInternalFieldPointer( ++ v8::Handle object ++ , int index ++ , void* value) { ++ object->SetPointerInInternalField(index, value); ++ } ++ ++ NAN_INLINE void NanAddGCEpilogueCallback( ++ v8::GCEpilogueCallback callback ++ , v8::GCType gc_type_filter = v8::kGCTypeAll) { ++ v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); ++ } ++ NAN_INLINE void NanRemoveGCEpilogueCallback( ++ v8::GCEpilogueCallback callback) { ++ v8::V8::RemoveGCEpilogueCallback(callback); ++ } ++ NAN_INLINE void NanAddGCPrologueCallback( ++ v8::GCPrologueCallback callback ++ , v8::GCType gc_type_filter = v8::kGCTypeAll) { ++ v8::V8::AddGCPrologueCallback(callback, gc_type_filter); ++ } ++ NAN_INLINE void NanRemoveGCPrologueCallback( ++ v8::GCPrologueCallback callback) { ++ v8::V8::RemoveGCPrologueCallback(callback); ++ } ++ NAN_INLINE void NanGetHeapStatistics( ++ v8::HeapStatistics *heap_statistics) { ++ v8::V8::GetHeapStatistics(heap_statistics); ++ } ++ ++ template ++ NAN_INLINE void NanAssignPersistent( ++ v8::Persistent& handle ++ , v8::Handle obj) { ++ handle.Dispose(); ++ handle = v8::Persistent::New(obj); ++ } ++ ++ template ++ class _NanWeakCallbackData; ++ ++ template ++ struct _NanWeakCallbackInfo { ++ typedef void (*Callback)(const _NanWeakCallbackData &data); ++ NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) ++ : parameter(param) ++ , callback(cb) ++ , persistent(v8::Persistent::New(handle)) { } ++ ++ NAN_INLINE ~_NanWeakCallbackInfo() { ++ persistent.Dispose(); ++ persistent.Clear(); ++ } ++ ++ P* const parameter; ++ Callback const callback; ++ v8::Persistent persistent; ++ }; ++ ++ template ++ class _NanWeakCallbackData { ++ public: ++ NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) ++ : info_(info) { } ++ ++ NAN_INLINE v8::Local GetValue() const { ++ return NanNew(info_->persistent); ++ } ++ ++ NAN_INLINE P* GetParameter() const { return info_->parameter; } ++ ++ NAN_INLINE bool IsNearDeath() const { ++ return info_->persistent.IsNearDeath(); ++ } ++ ++ NAN_INLINE void Revive() const; ++ ++ NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { ++ return info_; ++ } ++ ++ NAN_DEPRECATED NAN_INLINE void Dispose() const { ++ } ++ ++ private: ++ _NanWeakCallbackInfo* info_; ++ }; ++ ++ template ++ static void _NanWeakPersistentDispatcher( ++ v8::Persistent object, void *data) { ++ _NanWeakCallbackInfo* info = ++ static_cast<_NanWeakCallbackInfo*>(data); ++ _NanWeakCallbackData wcbd(info); ++ info->callback(wcbd); ++ if (wcbd.IsNearDeath()) { ++ delete wcbd.GetCallbackInfo(); ++ } ++ } ++ ++ template ++ NAN_INLINE void _NanWeakCallbackData::Revive() const { ++ info_->persistent.MakeWeak( ++ info_ ++ , &_NanWeakPersistentDispatcher); ++ } ++ ++ template ++ NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( ++ v8::Handle handle ++ , P* parameter ++ , typename _NanWeakCallbackInfo::Callback callback) { ++ _NanWeakCallbackInfo *cbinfo = ++ new _NanWeakCallbackInfo(handle, parameter, callback); ++ cbinfo->persistent.MakeWeak( ++ cbinfo ++ , &_NanWeakPersistentDispatcher); ++ return cbinfo; ++ } ++ ++# define NAN_WEAK_CALLBACK(name) \ ++ template \ ++ static void name(const _NanWeakCallbackData &data) ++ ++# define _NAN_ERROR(fun, errmsg) \ ++ fun(v8::String::New(errmsg)) ++ ++# define _NAN_THROW_ERROR(fun, errmsg) \ ++ do { \ ++ NanScope(); \ ++ return v8::Local::New( \ ++ v8::ThrowException(_NAN_ERROR(fun, errmsg))); \ ++ } while (0); ++ ++ NAN_INLINE v8::Local NanError(const char* errmsg) { ++ return _NAN_ERROR(v8::Exception::Error, errmsg); ++ } ++ ++ NAN_INLINE v8::Local NanThrowError(const char* errmsg) { ++ _NAN_THROW_ERROR(v8::Exception::Error, errmsg); ++ } ++ ++ NAN_INLINE v8::Local NanThrowError( ++ v8::Handle error ++ ) { ++ NanScope(); ++ return v8::Local::New(v8::ThrowException(error)); ++ } ++ ++ NAN_INLINE v8::Local NanError( ++ const char *msg ++ , const int errorNumber ++ ) { ++ v8::Local err = v8::Exception::Error(v8::String::New(msg)); ++ v8::Local obj = err.As(); ++ obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber)); ++ return err; ++ } ++ ++ NAN_INLINE v8::Local NanThrowError( ++ const char *msg ++ , const int errorNumber ++ ) { ++ return NanThrowError(NanError(msg, errorNumber)); ++ } ++ ++ NAN_INLINE v8::Local NanTypeError(const char* errmsg) { ++ return _NAN_ERROR(v8::Exception::TypeError, errmsg); ++ } ++ ++ NAN_INLINE v8::Local NanThrowTypeError( ++ const char* errmsg ++ ) { ++ _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); ++ } ++ ++ NAN_INLINE v8::Local NanRangeError( ++ const char* errmsg ++ ) { ++ return _NAN_ERROR(v8::Exception::RangeError, errmsg); ++ } ++ ++ NAN_INLINE v8::Local NanThrowRangeError( ++ const char* errmsg ++ ) { ++ _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); ++ } ++ ++ template ++ NAN_INLINE void NanDisposePersistent( ++ v8::Persistent &handle) { // NOLINT(runtime/references) ++ handle.Dispose(); ++ handle.Clear(); ++ } ++ ++ NAN_INLINE v8::Local NanNewBufferHandle ( ++ char *data ++ , size_t length ++ , node::Buffer::free_callback callback ++ , void *hint ++ ) { ++ return NanNew( ++ node::Buffer::New(data, length, callback, hint)->handle_); ++ } ++ ++ NAN_INLINE v8::Local NanNewBufferHandle ( ++ const char *data ++ , uint32_t size ++ ) { ++#if NODE_MODULE_VERSION >= 0x000B ++ return NanNew(node::Buffer::New(data, size)->handle_); ++#else ++ return NanNew( ++ node::Buffer::New(const_cast(data), size)->handle_); ++#endif ++ } ++ ++ NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { ++ return NanNew(node::Buffer::New(size)->handle_); ++ } ++ ++ NAN_INLINE void FreeData(char *data, void *hint) { ++ delete[] data; ++ } ++ ++ NAN_INLINE v8::Local NanBufferUse( ++ char* data ++ , uint32_t size ++ ) { ++ return NanNew( ++ node::Buffer::New(data, size, FreeData, NULL)->handle_); ++ } ++ ++ NAN_INLINE bool NanHasInstance( ++ v8::Persistent& function_template ++ , v8::Handle value ++ ) { ++ return function_template->HasInstance(value); ++ } ++ ++ NAN_INLINE v8::Local NanNewContextHandle( ++ v8::ExtensionConfiguration* extensions = NULL ++ , v8::Handle tmpl = v8::Handle() ++ , v8::Handle obj = v8::Handle() ++ ) { ++ v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); ++ v8::Local lctx = NanNew(ctx); ++ ctx.Dispose(); ++ return lctx; ++ } ++ ++ NAN_INLINE v8::Local NanCompileScript( ++ v8::Local s ++ , const v8::ScriptOrigin& origin ++ ) { ++ return v8::Script::Compile(s, const_cast(&origin)); ++ } ++ ++ NAN_INLINE v8::Local NanCompileScript( ++ v8::Local s ++ ) { ++ return v8::Script::Compile(s); ++ } ++ ++ NAN_INLINE v8::Local NanRunScript(v8::Handle script) { ++ return script->Run(); ++ } ++ ++ NAN_INLINE v8::Local NanMakeCallback( ++ v8::Handle target ++ , v8::Handle func ++ , int argc ++ , v8::Handle* argv) { ++# if NODE_VERSION_AT_LEAST(0, 8, 0) ++ return NanNew(node::MakeCallback(target, func, argc, argv)); ++# else ++ v8::TryCatch try_catch; ++ v8::Local result = NanNew(func->Call(target, argc, argv)); ++ if (try_catch.HasCaught()) { ++ node::FatalException(try_catch); ++ } ++ return result; ++# endif ++ } ++ ++ NAN_INLINE v8::Local NanMakeCallback( ++ v8::Handle target ++ , v8::Handle symbol ++ , int argc ++ , v8::Handle* argv) { ++# if NODE_VERSION_AT_LEAST(0, 8, 0) ++ return NanNew(node::MakeCallback(target, symbol, argc, argv)); ++# else ++ v8::Local callback = target->Get(symbol).As(); ++ return NanMakeCallback(target, callback, argc, argv); ++# endif ++ } ++ ++ NAN_INLINE v8::Local NanMakeCallback( ++ v8::Handle target ++ , const char* method ++ , int argc ++ , v8::Handle* argv) { ++# if NODE_VERSION_AT_LEAST(0, 8, 0) ++ return NanNew(node::MakeCallback(target, method, argc, argv)); ++# else ++ return NanMakeCallback(target, NanNew(method), argc, argv); ++# endif ++ } ++ ++ template ++ NAN_INLINE void NanSetIsolateData( ++ v8::Isolate *isolate ++ , T *data ++ ) { ++ isolate->SetData(data); ++ } ++ ++ template ++ NAN_INLINE T *NanGetIsolateData( ++ v8::Isolate *isolate ++ ) { ++ return static_cast(isolate->GetData()); ++ } ++ ++ class NanAsciiString { ++ public: ++ NAN_INLINE explicit NanAsciiString(v8::Handle from) { ++ v8::Local toStr = from->ToString(); ++ int buf_size = toStr->Length() + 1; ++ buf = new char[buf_size]; ++ size = toStr->WriteAscii(buf, 0, buf_size); ++ } ++ ++ NAN_INLINE int Size() const { ++ return size; ++ } ++ ++ NAN_INLINE char* operator*() { return buf; } ++ ++ NAN_INLINE ~NanAsciiString() { ++ delete[] buf; ++ } ++ ++ private: ++ char *buf; ++ int size; ++ }; ++ ++ class NanUtf8String { ++ public: ++ NAN_INLINE explicit NanUtf8String(v8::Handle from) { ++ v8::Local toStr = from->ToString(); ++ int buf_size = toStr->Utf8Length() + 1; ++ buf = new char[buf_size]; ++ size = toStr->WriteUtf8(buf, buf_size); ++ } ++ ++ NAN_INLINE int Size() const { ++ return size; ++ } ++ ++ NAN_INLINE char* operator*() { return buf; } ++ ++ NAN_INLINE ~NanUtf8String() { ++ delete[] buf; ++ } ++ ++ private: ++ char *buf; ++ int size; ++ }; ++ ++ class NanUcs2String { ++ public: ++ NAN_INLINE explicit NanUcs2String(v8::Handle from) { ++ v8::Local toStr = from->ToString(); ++ int buf_size = toStr->Length() + 1; ++ buf = new uint16_t[buf_size]; ++ size = toStr->Write(buf, 0, buf_size); ++ } ++ ++ NAN_INLINE int Size() const { ++ return size; ++ } ++ ++ NAN_INLINE uint16_t* operator*() { return buf; } ++ ++ NAN_INLINE ~NanUcs2String() { ++ delete[] buf; ++ } ++ ++ private: ++ uint16_t *buf; ++ int size; ++ }; ++ ++#endif // NODE_MODULE_VERSION ++ ++typedef void (*NanFreeCallback)(char *data, void *hint); ++ ++#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS) ++#define NAN_GETTER(name) \ ++ _NAN_GETTER_RETURN_TYPE name( \ ++ v8::Local property \ ++ , _NAN_GETTER_ARGS) ++#define NAN_SETTER(name) \ ++ _NAN_SETTER_RETURN_TYPE name( \ ++ v8::Local property \ ++ , v8::Local value \ ++ , _NAN_SETTER_ARGS) ++#define NAN_PROPERTY_GETTER(name) \ ++ _NAN_PROPERTY_GETTER_RETURN_TYPE name( \ ++ v8::Local property \ ++ , _NAN_PROPERTY_GETTER_ARGS) ++#define NAN_PROPERTY_SETTER(name) \ ++ _NAN_PROPERTY_SETTER_RETURN_TYPE name( \ ++ v8::Local property \ ++ , v8::Local value \ ++ , _NAN_PROPERTY_SETTER_ARGS) ++#define NAN_PROPERTY_ENUMERATOR(name) \ ++ _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS) ++#define NAN_PROPERTY_DELETER(name) \ ++ _NAN_PROPERTY_DELETER_RETURN_TYPE name( \ ++ v8::Local property \ ++ , _NAN_PROPERTY_DELETER_ARGS) ++#define NAN_PROPERTY_QUERY(name) \ ++ _NAN_PROPERTY_QUERY_RETURN_TYPE name( \ ++ v8::Local property \ ++ , _NAN_PROPERTY_QUERY_ARGS) ++# define NAN_INDEX_GETTER(name) \ ++ _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS) ++#define NAN_INDEX_SETTER(name) \ ++ _NAN_INDEX_SETTER_RETURN_TYPE name( \ ++ uint32_t index \ ++ , v8::Local value \ ++ , _NAN_INDEX_SETTER_ARGS) ++#define NAN_INDEX_ENUMERATOR(name) \ ++ _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS) ++#define NAN_INDEX_DELETER(name) \ ++ _NAN_INDEX_DELETER_RETURN_TYPE name( \ ++ uint32_t index \ ++ , _NAN_INDEX_DELETER_ARGS) ++#define NAN_INDEX_QUERY(name) \ ++ _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS) ++ ++class NanCallback { ++ public: ++ NanCallback() { ++ NanScope(); ++ v8::Local obj = NanNew(); ++ NanAssignPersistent(handle, obj); ++ } ++ ++ explicit NanCallback(const v8::Handle &fn) { ++ NanScope(); ++ v8::Local obj = NanNew(); ++ NanAssignPersistent(handle, obj); ++ SetFunction(fn); ++ } ++ ++ ~NanCallback() { ++ if (handle.IsEmpty()) return; ++ NanDisposePersistent(handle); ++ } ++ ++ NAN_INLINE void SetFunction(const v8::Handle &fn) { ++ NanScope(); ++ NanNew(handle)->Set(kCallbackIndex, fn); ++ } ++ ++ NAN_INLINE v8::Local GetFunction() const { ++ NanEscapableScope(); ++ return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex) ++ .As()); ++ } ++ ++ NAN_INLINE bool IsEmpty() const { ++ NanScope(); ++ return NanNew(handle)->Get(kCallbackIndex)->IsUndefined(); ++ } ++ ++ v8::Handle Call(int argc, v8::Handle argv[]) const { ++ NanEscapableScope(); ++#if (NODE_MODULE_VERSION > 0x000B) // 0.11.12+ ++ v8::Isolate* isolate = v8::Isolate::GetCurrent(); ++ v8::Local callback = NanNew(handle)-> ++ Get(kCallbackIndex).As(); ++ return NanEscapeScope(node::MakeCallback( ++ isolate ++ , isolate->GetCurrentContext()->Global() ++ , callback ++ , argc ++ , argv ++ )); ++#else ++#if NODE_VERSION_AT_LEAST(0, 8, 0) ++ v8::Local callback = handle-> ++ Get(kCallbackIndex).As(); ++ return NanEscapeScope(node::MakeCallback( ++ v8::Context::GetCurrent()->Global() ++ , callback ++ , argc ++ , argv ++ )); ++#else ++ v8::Local callback = handle-> ++ Get(kCallbackIndex).As(); ++ return NanEscapeScope(NanMakeCallback( ++ v8::Context::GetCurrent()->Global(), callback, argc, argv)); ++#endif ++#endif ++ } ++ ++ private: ++ v8::Persistent handle; ++ static const uint32_t kCallbackIndex = 0; ++}; ++ ++/* abstract */ class NanAsyncWorker { ++ public: ++ explicit NanAsyncWorker(NanCallback *callback) ++ : callback(callback), errmsg_(NULL) { ++ request.data = this; ++ ++ NanScope(); ++ v8::Local obj = NanNew(); ++ NanAssignPersistent(persistentHandle, obj); ++ } ++ ++ virtual ~NanAsyncWorker() { ++ NanScope(); ++ ++ if (!persistentHandle.IsEmpty()) ++ NanDisposePersistent(persistentHandle); ++ if (callback) ++ delete callback; ++ if (errmsg_) ++ delete[] errmsg_; ++ } ++ ++ virtual void WorkComplete() { ++ NanScope(); ++ ++ if (errmsg_ == NULL) ++ HandleOKCallback(); ++ else ++ HandleErrorCallback(); ++ delete callback; ++ callback = NULL; ++ } ++ ++ NAN_INLINE void SaveToPersistent( ++ const char *key, const v8::Local &obj) { ++ v8::Local handle = NanNew(persistentHandle); ++ handle->Set(NanNew(key), obj); ++ } ++ ++ v8::Local GetFromPersistent(const char *key) const { ++ NanEscapableScope(); ++ v8::Local handle = NanNew(persistentHandle); ++ return NanEscapeScope(handle->Get(NanNew(key)).As()); ++ } ++ ++ virtual void Execute() = 0; ++ ++ uv_work_t request; ++ ++ protected: ++ v8::Persistent persistentHandle; ++ NanCallback *callback; ++ ++ virtual void HandleOKCallback() { ++ NanScope(); ++ ++ callback->Call(0, NULL); ++ } ++ ++ virtual void HandleErrorCallback() { ++ NanScope(); ++ ++ v8::Local argv[] = { ++ v8::Exception::Error(NanNew(ErrorMessage())) ++ }; ++ callback->Call(1, argv); ++ } ++ ++ void SetErrorMessage(const char *msg) { ++ if (errmsg_) { ++ delete[] errmsg_; ++ } ++ ++ size_t size = strlen(msg) + 1; ++ errmsg_ = new char[size]; ++ memcpy(errmsg_, msg, size); ++ } ++ ++ const char* ErrorMessage() const { ++ return errmsg_; ++ } ++ ++ private: ++ char *errmsg_; ++}; ++ ++NAN_INLINE void NanAsyncExecute (uv_work_t* req) { ++ NanAsyncWorker *worker = static_cast(req->data); ++ worker->Execute(); ++} ++ ++NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) { ++ NanAsyncWorker* worker = static_cast(req->data); ++ worker->WorkComplete(); ++ delete worker; ++} ++ ++NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) { ++ uv_queue_work( ++ uv_default_loop() ++ , &worker->request ++ , NanAsyncExecute ++ , (uv_after_work_cb)NanAsyncExecuteComplete ++ ); ++} ++ ++//// Base 64 //// ++ ++#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) ++ ++// Doesn't check for padding at the end. Can be 1-2 bytes over. ++NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) { ++ size_t remainder = size % 4; ++ ++ size = (size / 4) * 3; ++ if (remainder) { ++ if (size == 0 && remainder == 1) { ++ // special case: 1-byte input cannot be decoded ++ size = 0; ++ } else { ++ // non-padded input, add 1 or 2 extra bytes ++ size += 1 + (remainder == 3); ++ } ++ } ++ ++ return size; ++} ++ ++template ++NAN_INLINE size_t _nan_base64_decoded_size( ++ const T* src ++ , size_t size ++) { ++ if (size == 0) ++ return 0; ++ ++ if (src[size - 1] == '=') ++ size--; ++ if (size > 0 && src[size - 1] == '=') ++ size--; ++ ++ return _nan_base64_decoded_size_fast(size); ++} ++ ++// supports regular and URL-safe base64 ++static const int _nan_unbase64_table[] = { ++ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++ , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63 ++ , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1 ++ , -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ++ , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63 ++ , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 ++ , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ++}; ++ ++#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)] ++ ++template static size_t _nan_base64_decode( ++ char* buf ++ , size_t len ++ , const T* src ++ , const size_t srcLen ++) { ++ char* dst = buf; ++ char* dstEnd = buf + len; ++ const T* srcEnd = src + srcLen; ++ ++ while (src < srcEnd && dst < dstEnd) { ++ ptrdiff_t remaining = srcEnd - src; ++ char a, b, c, d; ++ ++ while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; ++ if (remaining == 0 || *src == '=') break; ++ a = _nan_unbase64(*src++); ++ ++ while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; ++ if (remaining <= 1 || *src == '=') break; ++ b = _nan_unbase64(*src++); ++ ++ *dst++ = (a << 2) | ((b & 0x30) >> 4); ++ if (dst == dstEnd) break; ++ ++ while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; ++ if (remaining <= 2 || *src == '=') break; ++ c = _nan_unbase64(*src++); ++ ++ *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2); ++ if (dst == dstEnd) break; ++ ++ while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; ++ if (remaining <= 3 || *src == '=') break; ++ d = _nan_unbase64(*src++); ++ ++ *dst++ = ((c & 0x03) << 6) | (d & 0x3F); ++ } ++ ++ return dst - buf; ++} ++ ++//// HEX //// ++ ++template unsigned _nan_hex2bin(T c) { ++ if (c >= '0' && c <= '9') return c - '0'; ++ if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); ++ if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); ++ return static_cast(-1); ++} ++ ++template static size_t _nan_hex_decode( ++ char* buf ++ , size_t len ++ , const T* src ++ , const size_t srcLen ++) { ++ size_t i; ++ for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) { ++ unsigned a = _nan_hex2bin(src[i * 2 + 0]); ++ unsigned b = _nan_hex2bin(src[i * 2 + 1]); ++ if (!~a || !~b) return i; ++ buf[i] = a * 16 + b; ++ } ++ ++ return i; ++} ++ ++static bool _NanGetExternalParts( ++ v8::Handle val ++ , const char** data ++ , size_t* len ++) { ++ if (node::Buffer::HasInstance(val)) { ++ *data = node::Buffer::Data(val.As()); ++ *len = node::Buffer::Length(val.As()); ++ return true; ++ } ++ ++ assert(val->IsString()); ++ v8::Local str = NanNew(val.As()); ++ ++ if (str->IsExternalAscii()) { ++ const v8::String::ExternalAsciiStringResource* ext; ++ ext = str->GetExternalAsciiStringResource(); ++ *data = ext->data(); ++ *len = ext->length(); ++ return true; ++ ++ } else if (str->IsExternal()) { ++ const v8::String::ExternalStringResource* ext; ++ ext = str->GetExternalStringResource(); ++ *data = reinterpret_cast(ext->data()); ++ *len = ext->length(); ++ return true; ++ } ++ ++ return false; ++} ++ ++namespace Nan { ++ enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; ++} ++ ++/* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString( ++ v8::Handle from ++ , enum Nan::Encoding encoding ++ , size_t *datalen ++ , void *buf ++ , size_t buflen ++ , int flags ++) { ++ NanScope(); ++ ++ size_t sz_; ++ size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION); ++ char *data = NULL; ++ size_t len; ++ bool is_extern = _NanGetExternalParts( ++ from ++ , const_cast(&data) ++ , &len); ++ ++ if (is_extern && !term_len) { ++ NanSetPointerSafe(datalen, len); ++ return data; ++ } ++ ++ v8::Local toStr = from->ToString(); ++ ++ char *to = static_cast(buf); ++ ++ switch (encoding) { ++ case Nan::ASCII: ++#if NODE_MODULE_VERSION < 0x000C ++ sz_ = toStr->Length(); ++ if (to == NULL) { ++ to = new char[sz_ + term_len]; ++ } else { ++ assert(buflen >= sz_ + term_len && "too small buffer"); ++ } ++ NanSetPointerSafe( ++ datalen ++ , toStr->WriteAscii(to, 0, static_cast(sz_ + term_len), flags)); ++ return to; ++#endif ++ case Nan::BINARY: ++ case Nan::BUFFER: ++ sz_ = toStr->Length(); ++ if (to == NULL) { ++ to = new char[sz_ + term_len]; ++ } else { ++ assert(buflen >= sz_ + term_len && "too small buffer"); ++ } ++#if NODE_MODULE_VERSION < 0x000C ++ { ++ uint16_t* twobytebuf = new uint16_t[sz_ + term_len]; ++ ++ size_t len = toStr->Write(twobytebuf, 0, ++ static_cast(sz_ + term_len), flags); ++ ++ for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) { ++ unsigned char *b = reinterpret_cast(&twobytebuf[i]); ++ to[i] = *b; ++ } ++ ++ NanSetPointerSafe(datalen, len); ++ ++ delete[] twobytebuf; ++ return to; ++ } ++#else ++ NanSetPointerSafe( ++ datalen, ++ toStr->WriteOneByte( ++ reinterpret_cast(to) ++ , 0 ++ , static_cast(sz_ + term_len) ++ , flags)); ++ return to; ++#endif ++ case Nan::UTF8: ++ sz_ = toStr->Utf8Length(); ++ if (to == NULL) { ++ to = new char[sz_ + term_len]; ++ } else { ++ assert(buflen >= sz_ + term_len && "too small buffer"); ++ } ++ NanSetPointerSafe( ++ datalen ++ , toStr->WriteUtf8(to, static_cast(sz_ + term_len) ++ , NULL, flags) ++ - term_len); ++ return to; ++ case Nan::BASE64: ++ { ++ v8::String::Value value(toStr); ++ sz_ = _nan_base64_decoded_size(*value, value.length()); ++ if (to == NULL) { ++ to = new char[sz_ + term_len]; ++ } else { ++ assert(buflen >= sz_ + term_len); ++ } ++ NanSetPointerSafe( ++ datalen ++ , _nan_base64_decode(to, sz_, *value, value.length())); ++ if (term_len) { ++ to[sz_] = '\0'; ++ } ++ return to; ++ } ++ case Nan::UCS2: ++ { ++ sz_ = toStr->Length(); ++ if (to == NULL) { ++ to = new char[(sz_ + term_len) * 2]; ++ } else { ++ assert(buflen >= (sz_ + term_len) * 2 && "too small buffer"); ++ } ++ ++ int bc = 2 * toStr->Write( ++ reinterpret_cast(to) ++ , 0 ++ , static_cast(sz_ + term_len) ++ , flags); ++ NanSetPointerSafe(datalen, bc); ++ return to; ++ } ++ case Nan::HEX: ++ { ++ v8::String::Value value(toStr); ++ sz_ = value.length(); ++ assert(!(sz_ & 1) && "bad hex data"); ++ if (to == NULL) { ++ to = new char[sz_ / 2 + term_len]; ++ } else { ++ assert(buflen >= sz_ / 2 + term_len && "too small buffer"); ++ } ++ NanSetPointerSafe( ++ datalen ++ , _nan_hex_decode(to, sz_ / 2, *value, value.length())); ++ } ++ if (term_len) { ++ to[sz_ / 2] = '\0'; ++ } ++ return to; ++ default: ++ assert(0 && "unknown encoding"); ++ } ++ return to; ++} ++ ++NAN_DEPRECATED NAN_INLINE void* NanRawString( ++ v8::Handle from ++ , enum Nan::Encoding encoding ++ , size_t *datalen ++ , void *buf ++ , size_t buflen ++ , int flags ++) { ++ return _NanRawString(from, encoding, datalen, buf, buflen, flags); ++} ++ ++ ++NAN_DEPRECATED NAN_INLINE char* NanCString( ++ v8::Handle from ++ , size_t *datalen ++ , char *buf = NULL ++ , size_t buflen = 0 ++ , int flags = v8::String::NO_OPTIONS ++) { ++ return static_cast( ++ _NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags) ++ ); ++} ++ ++NAN_INLINE void NanSetPrototypeTemplate( ++ v8::Local templ ++ , const char *name ++ , v8::Handle value ++) { ++ NanSetTemplate(templ->PrototypeTemplate(), name, value); ++} ++ ++NAN_INLINE void NanSetPrototypeTemplate( ++ v8::Local templ ++ , v8::Handle name ++ , v8::Handle value ++ , v8::PropertyAttribute attributes ++) { ++ NanSetTemplate(templ->PrototypeTemplate(), name, value, attributes); ++} ++ ++NAN_INLINE void NanSetInstanceTemplate( ++ v8::Local templ ++ , const char *name ++ , v8::Handle value ++) { ++ NanSetTemplate(templ->InstanceTemplate(), name, value); ++} ++ ++NAN_INLINE void NanSetInstanceTemplate( ++ v8::Local templ ++ , v8::Handle name ++ , v8::Handle value ++ , v8::PropertyAttribute attributes ++) { ++ NanSetTemplate(templ->InstanceTemplate(), name, value, attributes); ++} ++ ++#endif // NAN_H_ diff --git a/lang/node-serialport/Makefile b/lang/node-serialport/Makefile new file mode 100644 index 0000000000..56d0697b39 --- /dev/null +++ b/lang/node-serialport/Makefile @@ -0,0 +1,60 @@ +# +# Copyright (C) 2014 Arduino LLC +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NPM_NAME:=serialport +PKG_NAME:=node-$(PKG_NPM_NAME) +PKG_VERSION:=1.4.6 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NPM_NAME)-$(PKG_VERSION).tgz +PKG_SOURCE_URL:=http://registry.npmjs.org/$(PKG_NPM_NAME)/-/ +PKG_MD5SUM:=1eb21082e0aa676b8350182a60230808 + +PKG_BUILD_DEPENDS:=node +PKG_NODE_VERSION:=0.12.7 + +PKG_MAINTAINER:=John Crispin + +include $(INCLUDE_DIR)/package.mk + +define Package/node-serialport + DEPENDS:=+node + SUBMENU:=Node.js + SECTION:=lang + CATEGORY:=Languages + TITLE:=Node.js package to access serial ports for reading and writing + URL:=https://www.npmjs.org/package/serialport +endef + +define Package/node-serialport/description + Node.js package to access serial ports for reading and writing OR Welcome your robotic JavaScript overlords. Better yet, program them! +endef + +define Build/Prepare + /bin/tar xzf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip-components 1 + $(Build/Patch) +endef + +EXTRA_LDFLAGS="-L$(TOOLCHAIN_DIR)/lib/ -Wl,-rpath-link $(TOOLCHAIN_DIR)/lib/" \ + +define Build/Compile + $(MAKE_FLAGS) \ + npm_config_arch=$(CONFIG_ARCH) \ + npm_config_nodedir=$(BUILD_DIR)/node-v$(PKG_NODE_VERSION)/ \ + PREFIX="$(PKG_INSTALL_DIR)/usr/" \ + $(STAGING_DIR_HOST)/bin/npm install -g $(PKG_BUILD_DIR) +endef + +define Package/node-serialport/install + mkdir -p $(1)/usr/lib/node/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/* $(1)/usr/lib/node/ +endef + +$(eval $(call BuildPackage,node-serialport)) + diff --git a/lang/node-serialport/patches/package.json.patch b/lang/node-serialport/patches/package.json.patch new file mode 100644 index 0000000000..a20c6a5a22 --- /dev/null +++ b/lang/node-serialport/patches/package.json.patch @@ -0,0 +1,11 @@ +--- a/package.json 2014-05-02 12:02:02.940515727 +0200 ++++ b/package.json 2014-05-02 12:03:08.488512762 +0200 +@@ -69,7 +71,7 @@ + "serialportterm": "./bin/serialportTerminal.js" + }, + "scripts": { +- "install": "node-pre-gyp install --fallback-to-build", ++ "install": "node-pre-gyp reinstall --build-from-source --target_arch=${npm_config_arch}", + "test": "grunt --verbose" + } + } diff --git a/lang/node/Makefile b/lang/node/Makefile new file mode 100644 index 0000000000..98a76b88cd --- /dev/null +++ b/lang/node/Makefile @@ -0,0 +1,71 @@ +# +# Copyright (C) 2006-2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=node +PKG_VERSION:=v0.12.7 +PKG_RELEASE:=1 + +PKG_SOURCE:=node-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://nodejs.org/dist/${PKG_VERSION} + +PKG_INSTALL:=1 + +PKG_MAINTAINER:=John Crispin +PKG_LICENSE:= + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/package.mk + +define Package/node + SECTION:=lang + CATEGORY:=Languages + SUBMENU:=Node.js + TITLE:=Node.js is a platform built on Chrome's JavaScript runtime + URL:=http://nodejs.org/ + DEPENDS:=+libpthread +librt +libstdcpp +libopenssl +libuv +endef + +define Package/node/description + Node.jsĀ® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses + an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' + package ecosystem, npm, is the largest ecosystem of open source libraries in the world. +endef + +CONFIGURE_ARGS= \ + --dest-cpu=$(CONFIG_ARCH) \ + --dest-os=linux \ + --without-snapshot \ + --shared-zlib \ + --shared-openssl \ + --prefix=/usr + +HOST_CONFIGURE_VARS:= +HOST_CONFIGURE_ARGS:= \ + --dest-os=linux \ + --without-snapshot \ + --prefix=$(STAGING_DIR_HOST)/ + +HOST_CONFIGURE_CMD:=python ./configure + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/ +endef + +define Package/node/install + mkdir -p $(1)/usr/bin $(1)/usr/lib/node_modules/npm/{bin,lib,node_modules} + $(CP) $(PKG_INSTALL_DIR)/usr/bin/{node,npm} $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/npm/{package.json,LICENSE,cli.js} $(1)/usr/lib/node_modules/npm + $(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/npm/bin/npm-cli.js $(1)/usr/lib/node_modules/npm/bin + $(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/npm/lib/* $(1)/usr/lib/node_modules/npm/lib/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/npm/node_modules/* $(1)/usr/lib/node_modules/npm/node_modules/ +endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,node)) diff --git a/lang/node/patches/001-mips-no-fpu.patch b/lang/node/patches/001-mips-no-fpu.patch new file mode 100644 index 0000000000..5bf8142cca --- /dev/null +++ b/lang/node/patches/001-mips-no-fpu.patch @@ -0,0 +1,15 @@ +--- a/deps/v8/build/toolchain.gypi ++++ b/deps/v8/build/toolchain.gypi +@@ -50,10 +50,10 @@ + 'arm_test_noprobe%': 'off', + + # Similar to vfp but on MIPS. +- 'v8_can_use_fpu_instructions%': 'true', ++ 'v8_can_use_fpu_instructions%': 'false', + + # Similar to the ARM hard float ABI but on MIPS. +- 'v8_use_mips_abi_hardfloat%': 'true', ++ 'v8_use_mips_abi_hardfloat%': 'false', + + # Default arch variant for MIPS. + 'mips_arch_variant%': 'r2', diff --git a/lang/node/patches/002-addr_info.patch b/lang/node/patches/002-addr_info.patch new file mode 100644 index 0000000000..78225db55b --- /dev/null +++ b/lang/node/patches/002-addr_info.patch @@ -0,0 +1,10 @@ +--- a/deps/uv/src/unix/getaddrinfo.c ++++ b/deps/uv/src/unix/getaddrinfo.c +@@ -99,6 +99,7 @@ + int err; + + req = container_of(w, uv_getaddrinfo_t, work_req); ++ req->hints->ai_flags &= ~AI_V4MAPPED; + err = getaddrinfo(req->hostname, req->service, req->hints, &req->addrinfo); + req->retcode = uv__getaddrinfo_translate_error(err); + } diff --git a/lang/node/patches/003-path.patch b/lang/node/patches/003-path.patch new file mode 100644 index 0000000000..723fe9da7d --- /dev/null +++ b/lang/node/patches/003-path.patch @@ -0,0 +1,12 @@ +--- a/lib/module.js ++++ b/lib/module.js +@@ -512,7 +512,8 @@ + var homeDir = process.env.HOME; + } + +- var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')]; ++ var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node'), ++ path.resolve(process.execPath, '..', '..', 'lib', 'node_modules')]; + + if (homeDir) { + paths.unshift(path.resolve(homeDir, '.node_libraries'));