├── .gitignore ├── LICENSE ├── README.md ├── commonjs ├── cjsfile.cpp ├── cjsfile.h ├── cjsprocess.cpp ├── cjsprocess.h ├── commonjs.cpp ├── commonjs.h ├── commonjs.pri ├── lib │ ├── _debugger.js │ ├── _http_agent.js │ ├── _http_client.js │ ├── _http_common.js │ ├── _http_incoming.js │ ├── _http_outgoing.js │ ├── _http_server.js │ ├── _linklist.js │ ├── _stream_duplex.js │ ├── _stream_passthrough.js │ ├── _stream_readable.js │ ├── _stream_transform.js │ ├── _stream_writable.js │ ├── _tls_legacy.js │ ├── _tls_wrap.js │ ├── assert.js │ ├── buffer.js │ ├── child_process.js │ ├── cluster.js │ ├── console.js │ ├── constants.js │ ├── crypto.js │ ├── dgram.js │ ├── dns.js │ ├── domain.js │ ├── events.js │ ├── freelist.js │ ├── fs.js │ ├── http.js │ ├── https.js │ ├── module.js │ ├── net.js │ ├── os.js │ ├── path.js │ ├── punycode.js │ ├── querystring.js │ ├── readline.js │ ├── repl.js │ ├── smalloc.js │ ├── stream.js │ ├── string_decoder.js │ ├── sys.js │ ├── timers.js │ ├── tls.js │ ├── tty.js │ ├── url.js │ ├── util.js │ ├── vm.js │ └── zlib.js ├── resources.qrc └── templates │ └── require.qml ├── plugin ├── commonjs_plugin.cpp ├── commonjs_plugin.h ├── plugin.pro └── qmldir └── tests ├── commonjs-tests.pro ├── js ├── bootstrap.js ├── config.json ├── main.js ├── no-package-json │ └── index.js ├── node_modules │ └── testmodule │ │ ├── custom-main-file.js │ │ └── package.json └── package-json │ ├── custom-main-file.js │ └── package.json ├── main.cpp ├── node_modules └── inparentfolder │ ├── custom-main-file.js │ └── package.json └── qml └── main.qml /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | *.pro.user 16 | *.pro.user.* 17 | moc_*.cpp 18 | qrc_*.cpp 19 | Makefile 20 | *-build-* 21 | .qmake.stash 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Dmitriy Kubyshkin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DISCONTINUED 2 | 3 | > **Notice:** Unfortunately I can not commit to supporting and further development of this project. Please check [Quickly](https://github.com/quickly/quickly/) which provides similar, or better functionality. If you are still interested in becoming an owner / maintainer please submit an issue and I will get back to you. 4 | 5 | # QML CommonJS 6 | 7 | Experiment in adding CommonJS module support to QML. 8 | 9 | ## Changelog 10 | 11 | ### Version 0.2 12 | 13 | * Fixed compatibility with Qt 5.4+ (see changes below for details). 14 | * **CHANGED** paths for `CommonJS.require` calls from QML are now resolved relative to `QmlEngine::baseUrl()` because evaluating `Qt.resolvedUrl('.')` no longer works from CPP code for some reason. 15 | * **CHANGED** evaluated module is now wrapped in an [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression) to avoid weird problem where function with a name same a property on a global object (e.g. `hasOwnProperty`) would result in an error. 16 | 17 | ### Version 0.1 18 | 19 | * Full [modules](http://nodejs.org/api/modules.html) support 20 | * `assert` module 21 | * `setTimeout` / `clearTimeout` / `setInterval` / `clearInterval` 22 | * experimental support for `util`, `events`, `path`, `url` and `querystring` modules. 23 | 24 | When accessing top-level functions (like `setTimeout`) from QML, you have to use `CommonJS.` prefix because Qt doesn't allow defining global functions. 25 | 26 | ## Installation 27 | 28 | * Make sure you have [Qt 5.4+](https://www.qt.io/) installed. 29 | * Clone this repository. 30 | * Then run `qmake && make && make install` 31 | 32 | ## Usage 33 | 34 | After that you should be able to just import CommonJS as regular QML library and use it in your code: 35 | 36 | ```js 37 | import CommonJS 0.2 38 | import QtQuick 2.0 39 | 40 | Rectangle { 41 | Component.onCompleted: { 42 | CommonJS.setTimeout(function(){ 43 | // built-in module 44 | var example = CommonJS.require('path'); 45 | // relative to QML base url 46 | var example = CommonJS.require('./example.js'); 47 | // relative to this file 48 | var example = CommonJS.require(Qt.resolvedUrl('./example.js')); 49 | }); 50 | } 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /commonjs/cjsfile.cpp: -------------------------------------------------------------------------------- 1 | #include "cjsfile.h" 2 | #include "sys/stat.h" 3 | #include "QDebug" 4 | 5 | CJSFile::CJSFile(CommonJS *main) : QObject(main), m_main(main) 6 | { 7 | m_stat = main->scriptEngine()->evaluate( 8 | "(function stat(path, callback){" 9 | " if(stat.native.doStat(path, callback) !== 0) throw new Error;" 10 | "})"); 11 | m_stat.setProperty("native", main->scriptEngine()->newQObject(this)); 12 | } 13 | 14 | int CJSFile::doStat(QString path, QJSValue callback) 15 | { 16 | Q_UNUSED(callback); 17 | struct ::stat result; 18 | int code = ::stat(path.toStdString().c_str(), &result); 19 | if(code != 0) { 20 | 21 | } 22 | return code; 23 | } 24 | -------------------------------------------------------------------------------- /commonjs/cjsfile.h: -------------------------------------------------------------------------------- 1 | #ifndef CJSFILE_H 2 | #define CJSFILE_H 3 | 4 | #include 5 | #include 6 | #include "commonjs.h" 7 | 8 | class CJSFile : public QObject 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(QJSValue Stats READ StatsConstuctor WRITE setStatsConstuctor) 12 | Q_PROPERTY(QJSValue stat READ stat) 13 | 14 | 15 | public: 16 | explicit CJSFile(CommonJS *main); 17 | 18 | QJSValue StatsConstuctor() const { return m_StatsConstructor; } 19 | 20 | QJSValue stat() const { return m_stat; } 21 | Q_INVOKABLE int doStat(QString path, QJSValue callback); 22 | 23 | signals: 24 | 25 | public slots: 26 | void setStatsConstuctor(QJSValue jsFunc) { m_StatsConstructor = jsFunc; } 27 | 28 | protected: 29 | CommonJS *m_main; 30 | QJSValue m_stat, m_StatsConstructor; 31 | }; 32 | 33 | #endif // CJSFILE_H 34 | -------------------------------------------------------------------------------- /commonjs/cjsprocess.cpp: -------------------------------------------------------------------------------- 1 | #include "cjsprocess.h" 2 | #include "commonjs.h" 3 | 4 | // Gives access to process ENV 5 | // Necessary for function related to gid / uid 6 | #ifndef Q_OS_WIN 7 | #include 8 | #include 9 | #endif 10 | 11 | #include 12 | extern char **environ; 13 | 14 | /** 15 | * @brief This classed is used in implementation of nextTick() method 16 | */ 17 | class CJSTickEvent : public QEvent { 18 | public: 19 | CJSTickEvent() : QEvent(CJSTickEvent::type()) {} 20 | 21 | static QEvent::Type type() 22 | { 23 | if (customEventType == QEvent::None) 24 | { 25 | int generatedType = QEvent::registerEventType(); 26 | customEventType = static_cast(generatedType); 27 | } 28 | return customEventType; 29 | } 30 | 31 | private: 32 | static QEvent::Type customEventType; 33 | }; 34 | QEvent::Type CJSTickEvent::customEventType = QEvent::None; 35 | 36 | 37 | 38 | /////////////////////////////////////////////////////////////////////////////// 39 | // Start implementation of CJSProcess 40 | /////////////////////////////////////////////////////////////////////////////// 41 | 42 | // POSIX-specific methods 43 | #ifndef Q_OS_WIN 44 | int CJSProcess::getgid() const { return getgid();} 45 | void CJSProcess::setgid(int gid) const { setgid(gid); } 46 | int CJSProcess::getuid() const { return getuid(); } 47 | void CJSProcess::setuid(int uid) const { setuid(uid); } 48 | #endif 49 | 50 | void CJSProcess::nextTick(QJSValue callback = QJSValue()) 51 | { 52 | if(!callback.isCallable()) { 53 | return; 54 | } 55 | m_nextTickCallbacks.append(callback); 56 | 57 | // There's no point in posting multiple events 58 | if(!m_tickEventPosted) { 59 | // posting event with maximum priority because we want to be 60 | // processed before any other events (like IO) 61 | qApp->postEvent(this, new CJSTickEvent(), INT_MAX); 62 | m_tickEventPosted = true; 63 | } 64 | } 65 | 66 | QString CJSProcess::version() const 67 | { 68 | return QString("%1.%2") 69 | .arg(CommonJS::majorVersion) 70 | .arg(CommonJS::minorVersion); 71 | } 72 | 73 | QString CJSProcess::platform() const 74 | { 75 | #ifdef Q_OS_WIN 76 | return "win32"; 77 | #endif 78 | #ifdef Q_OS_FREEBSD 79 | return "freebsd"; 80 | #endif 81 | #ifdef Q_OS_DARWIN 82 | return "darwin"; 83 | #endif 84 | #ifdef Q_OS_DARWIN64 85 | return "darwin"; 86 | #endif 87 | #ifdef Q_OS_LINUX 88 | return "linux"; 89 | #endif 90 | #ifdef Q_OS_SOLARIS 91 | return "sunos"; 92 | #endif 93 | return "unknown"; 94 | } 95 | 96 | QVariantMap CJSProcess::env() 97 | { 98 | QVariantMap envMap; 99 | char *s = *environ; 100 | for (int i = 0; s; i++) { 101 | QStringList pair = QString(s).split("="); 102 | envMap.insert(pair.first(), pair.last()); 103 | s = *(environ+i); 104 | } 105 | return envMap; 106 | } 107 | 108 | /** 109 | * @brief Used to catch CJSTickEvent 110 | * @return 111 | */ 112 | void CJSProcess::customEvent(QEvent *e) 113 | { 114 | if(e->type() == CJSTickEvent::type()) { 115 | // need to reset this so callbacks can call nextTick too 116 | m_tickEventPosted = false; 117 | 118 | // creating a copy of the list because otherwise 119 | // calls to nextTick() will be added to current list 120 | // of callbacks which may result in an infinite loop 121 | QList callbacks = m_nextTickCallbacks; 122 | m_nextTickCallbacks.clear(); 123 | 124 | while(callbacks.length()) { 125 | callbacks.takeFirst().call(); 126 | } 127 | } else { 128 | QObject::customEvent(e); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /commonjs/cjsprocess.h: -------------------------------------------------------------------------------- 1 | #ifndef CJSPROCESS_H 2 | #define CJSPROCESS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "commonjs.h" 11 | 12 | class CJSProcess : public QObject 13 | { 14 | Q_OBJECT 15 | Q_PROPERTY(QStringList argv READ argv) 16 | Q_PROPERTY(QString execPath READ execPath) 17 | Q_PROPERTY(QStringList execArgv READ execArgv) 18 | Q_PROPERTY(QVariantMap env READ env) 19 | Q_PROPERTY(QString version READ version) 20 | Q_PROPERTY(QString platform READ platform) 21 | 22 | public: 23 | explicit CJSProcess(CommonJS *main = 0) 24 | : QObject(main), m_main(main), m_tickEventPosted(false) {} 25 | 26 | QStringList argv() const { return qApp->arguments(); } 27 | QString execPath() const { return qApp->applicationFilePath(); } 28 | Q_INVOKABLE QString pwd() const { return QDir::currentPath(); } 29 | Q_INVOKABLE void chdir(QString path) const { QDir::setCurrent(path); } 30 | 31 | // Since we don't support node-specific arguments this list is always empty 32 | QStringList execArgv() const { return QStringList(); } 33 | 34 | Q_INVOKABLE QJSValue binding(QString name) { return m_main->binding(name); } 35 | QString version() const; 36 | QString platform() const; 37 | QVariantMap env(); 38 | 39 | /* This may not do what common js modules expect according to nodejs docs: 40 | * "This causes node to emit an abort. 41 | * This will cause node to exit and generate a core file." 42 | */ 43 | Q_INVOKABLE void abort() const { exit(1); } 44 | 45 | Q_INVOKABLE void exit(int code = 0) const { qApp->exit(code); } 46 | 47 | #ifndef Q_WS_WIN 48 | Q_INVOKABLE int getgid() const; 49 | Q_INVOKABLE void setgid(int gid) const; 50 | Q_INVOKABLE int getuid() const; 51 | Q_INVOKABLE void setuid(int uid) const; 52 | #endif 53 | 54 | Q_INVOKABLE void nextTick(QJSValue callback); 55 | 56 | protected: 57 | CommonJS *m_main; 58 | bool m_tickEventPosted; 59 | QList m_nextTickCallbacks; 60 | void customEvent(QEvent *e); 61 | 62 | }; 63 | 64 | #endif // CJSPROCESS_H 65 | -------------------------------------------------------------------------------- /commonjs/commonjs.cpp: -------------------------------------------------------------------------------- 1 | #include "commonjs.h" 2 | #include "cjsprocess.h" 3 | #include "cjsfile.h" 4 | #include 5 | 6 | /** 7 | * @brief Singleton class exposed to QML context 8 | * @param engine 9 | * @param scriptEngine 10 | */ 11 | CommonJS::CommonJS(QQmlEngine *engine, QJSEngine *scriptEngine) 12 | : QObject(NULL), m_engine(engine), m_scriptEngine(scriptEngine) 13 | { 14 | m_cache = m_scriptEngine->newObject(); 15 | m_global = m_scriptEngine->newObject(); 16 | m_process = m_scriptEngine->newQObject(new CJSProcess(this)); 17 | m_cjsFile = new CJSFile(this); 18 | initRequireJSCode(); 19 | } 20 | 21 | int CommonJS::minorVersion = 2; 22 | int CommonJS::majorVersion = 0; 23 | 24 | /** 25 | * @internal 26 | * @param url 27 | * @return 28 | */ 29 | QString CommonJS::__loadFile(QString url) 30 | { 31 | QFile file(url); 32 | QString fileContent; 33 | 34 | if ( file.open(QIODevice::ReadOnly) ) {; 35 | QTextStream t( &file ); 36 | fileContent = t.readAll(); 37 | file.close(); 38 | } else { // TODO check what node does in this case 39 | return QString(); 40 | } 41 | 42 | return fileContent; 43 | } 44 | 45 | /** 46 | * @brief Calls a JS function after a specified delay. 47 | * @param callback JS function 48 | * @param delay 49 | * @return 50 | */ 51 | int CommonJS::setTimeout(QJSValue callback, int delay) 52 | { 53 | if(delay < 0) { 54 | delay = 0; 55 | } 56 | 57 | int timerId = startTimer(delay, Qt::PreciseTimer); 58 | m_setTimeoutCallbacks.insert(timerId, callback); 59 | 60 | return timerId; 61 | } 62 | 63 | /** 64 | * @brief Clears delayed function or code snippet set by setTimeout 65 | * @param timeoutId 66 | * @return 67 | */ 68 | void CommonJS::clearTimeout(int timeoutId) 69 | { 70 | if(m_setTimeoutCallbacks.contains(timeoutId)) { 71 | m_setTimeoutCallbacks.remove(timeoutId); 72 | killTimer(timeoutId); 73 | } 74 | } 75 | 76 | /** 77 | * @brief Calls a JS function with a specified interval. 78 | * @param callback JS function 79 | * @param delay 80 | * @return 81 | */ 82 | int CommonJS::setInterval(QJSValue callback, int interval) 83 | { 84 | if(interval < 0) { 85 | interval = 0; 86 | } 87 | 88 | int timerId = startTimer((interval < 0), Qt::PreciseTimer); 89 | m_setIntervalCallbacks.insert(timerId, callback); 90 | 91 | return timerId; 92 | } 93 | 94 | 95 | /** 96 | * @brief Clears interval function or code snippet set by setInterval 97 | * @param timeoutId 98 | * @return 99 | */ 100 | void CommonJS::clearInterval(int intervalId) 101 | { 102 | if(m_setIntervalCallbacks.contains(intervalId)) { 103 | m_setIntervalCallbacks.remove(intervalId); 104 | killTimer(intervalId); 105 | } 106 | } 107 | 108 | /** 109 | * @brief Used for implementation of setTimeout / setInterval 110 | * @param event 111 | * @internal 112 | */ 113 | void CommonJS::timerEvent(QTimerEvent *event) { 114 | QJSValue callback; 115 | if(m_setTimeoutCallbacks.contains(event->timerId())) { 116 | callback = m_setTimeoutCallbacks[event->timerId()]; 117 | m_setTimeoutCallbacks.remove(event->timerId()); 118 | killTimer(event->timerId()); 119 | event->accept(); 120 | } else if(m_setIntervalCallbacks.contains(event->timerId())) { 121 | callback = m_setIntervalCallbacks[event->timerId()]; 122 | event->accept(); 123 | } 124 | 125 | if(!callback.isUndefined()) { 126 | if(callback.isCallable()) { 127 | callback.call(); 128 | } else { // if isn't a function callback is treated as snippet of code 129 | m_scriptEngine->evaluate(callback.toString()); 130 | } 131 | } 132 | } 133 | 134 | QJSValue CommonJS::binding(QString name) const 135 | { 136 | QJSValue result = m_scriptEngine->newObject(); 137 | if(name == "fs") { 138 | result = m_scriptEngine->newQObject(m_cjsFile); 139 | result.setProperty("stat", m_scriptEngine->evaluate("(function(){ throw new Error; })")); 140 | } else if(name == "constants") { 141 | // TODO need to do this properly and probably platform-dependent 142 | result.setProperty("S_IFMT", 0b11110000000000); 143 | result.setProperty("O_APPEND", 0b1000); 144 | result.setProperty("O_CREAT", 0b1000000000); 145 | result.setProperty("O_DIRECTORY", 0b100000000000000000000); 146 | result.setProperty("O_EXCL", 0b100000000000); 147 | result.setProperty("O_NOCTTY", 0b100000000000000000); 148 | result.setProperty("O_NOFOLLOW", 0b100000000); 149 | result.setProperty("O_RDONLY", 0b0); 150 | result.setProperty("O_RDWR", 0b10); 151 | result.setProperty("O_SYMLINK", 0b1000000000000000000000); 152 | result.setProperty("O_SYNC", 0b10000000); 153 | result.setProperty("O_TRUNC", 0b10000000000); 154 | result.setProperty("O_WRONLY", 0b1); 155 | } 156 | 157 | return result; 158 | } 159 | 160 | /** 161 | * @brief Returns QJSValue representing required js file module.exports 162 | * @param url 163 | * @return 164 | */ 165 | QJSValue CommonJS::require(QString url) 166 | { 167 | // Creating a fake parent module to avoid additional logic inside 168 | // main require function to deal with requiring from QML code 169 | QJSValue qmlParentModule = m_scriptEngine->newObject(); 170 | qmlParentModule.setProperty("id", m_engine->baseUrl().toString()); 171 | qmlParentModule.setProperty("children", m_scriptEngine->newArray()); 172 | 173 | QJSValue result = m_require.call(QJSValueList() << url << qmlParentModule); 174 | if(result.isError()) { 175 | m_scriptEngine->evaluate("console.error").call(QJSValueList() << result); 176 | } 177 | return result; 178 | } 179 | 180 | /** 181 | * @brief Compiles require js support code in an empty context 182 | * @internal 183 | */ 184 | void CommonJS::initRequireJSCode() 185 | { 186 | // Creating component in an empty context so that required code 187 | // won't affect any global variables defined in calling context 188 | QQmlContext *context = new QQmlContext(m_engine); 189 | QQmlComponent component(m_engine); 190 | 191 | // Sandboxed version of require funciton is available 192 | // inside lightest possible QML component loaded here 193 | QString requireCode = __loadFile(":/templates/require.qml"); 194 | 195 | // Now creating the component to compile our require functions 196 | component.setData(requireCode.toUtf8(), QUrl()); 197 | QObject *obj = component.create(context); 198 | QJSValue jsObj = m_engine->newQObject(obj); 199 | 200 | // Getting compiled version of require function from QML object 201 | m_require = jsObj.property("requireInitializer"); 202 | m_resolve = jsObj.property("resolveInitializer"); 203 | 204 | // Making CommonJS singleton available inside require and resolve function 205 | // to be able to refer back to it without relying on CommonJS QML modul 206 | // being imported into global namespace (without `as SomeIdentifier`) 207 | m_require = m_require.call(QJSValueList() << m_scriptEngine->newQObject(this)); 208 | m_resolve = m_resolve.call(QJSValueList() << m_scriptEngine->newQObject(this)); 209 | m_cjsFile->setStatsConstuctor(jsObj.property("createFsStatsConstructor").call()); 210 | } 211 | -------------------------------------------------------------------------------- /commonjs/commonjs.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMONJS_H 2 | #define COMMONJS_H 3 | 4 | #include 5 | #include 6 | 7 | class CJSFile; 8 | 9 | class CommonJS : public QObject 10 | { 11 | Q_OBJECT 12 | Q_DISABLE_COPY(CommonJS) 13 | Q_PROPERTY(QJSValue cache READ cache) 14 | Q_PROPERTY(QJSValue global READ global) 15 | Q_PROPERTY(QJSValue process READ process) 16 | Q_PROPERTY(QJSValue resolve READ resolve) 17 | 18 | public: 19 | explicit CommonJS(QQmlEngine *engine, QJSEngine *scriptEngine); 20 | 21 | 22 | Q_INVOKABLE QJSValue require(QString url); 23 | QJSValue resolve() const { return m_resolve; } 24 | QJSValue cache() const { return m_cache; } 25 | QJSValue global() const { return m_global; } 26 | QJSValue process() const { return m_process; } 27 | 28 | // Pseudo-private function that is only public 29 | // so that javascript code will have access to them 30 | Q_INVOKABLE QString __loadFile(QString url); 31 | 32 | Q_INVOKABLE int setTimeout(QJSValue callback = QJSValue(), int delay = 0); 33 | Q_INVOKABLE void clearTimeout(int timeoutId = 0); 34 | Q_INVOKABLE int setInterval(QJSValue callback = QJSValue(), int interval = 0); 35 | Q_INVOKABLE void clearInterval(int intervalId = 0); 36 | QJSValue binding(QString name) const; 37 | 38 | // QML singleton provider for usage with qmlRegisterSingletonType<> 39 | static QObject* singletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine) 40 | { 41 | return new CommonJS(engine, scriptEngine); 42 | } 43 | 44 | // Convenince function for registering CommonJS in QML 45 | static void registerQmlSingletonType(const char *uri = "CommonJS") 46 | { 47 | // @uri CommonJS 48 | qmlRegisterSingletonType(uri, majorVersion, minorVersion, "CommonJS", singletonProvider); 49 | } 50 | 51 | static int majorVersion; 52 | static int minorVersion; 53 | 54 | QJSEngine *scriptEngine() const { return m_scriptEngine; } 55 | 56 | protected: 57 | void initRequireJSCode(); 58 | QHash m_setTimeoutCallbacks; 59 | QHash m_setIntervalCallbacks; 60 | QJSValue m_process, m_global, m_cache, m_require, m_resolve, m_fsStats; 61 | QQmlEngine *m_engine; 62 | QJSEngine *m_scriptEngine; 63 | CJSFile *m_cjsFile; 64 | 65 | // overloaded methods 66 | void timerEvent(QTimerEvent *event); 67 | 68 | }; 69 | 70 | #endif // COMMONJS_H 71 | 72 | -------------------------------------------------------------------------------- /commonjs/commonjs.pri: -------------------------------------------------------------------------------- 1 | SOURCES += \ 2 | $$PWD/commonjs.cpp \ 3 | ../commonjs/cjsprocess.cpp \ 4 | ../commonjs/cjsfile.cpp 5 | 6 | HEADERS += \ 7 | $$PWD/commonjs.h \ 8 | ../commonjs/cjsprocess.h \ 9 | ../commonjs/cjsfile.h 10 | 11 | OTHER_FILES += \ 12 | $$PWD/templates/require.qml 13 | 14 | RESOURCES += \ 15 | $$PWD/resources.qrc 16 | 17 | INCLUDEPATH += $$PWD 18 | -------------------------------------------------------------------------------- /commonjs/lib/_http_agent.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var net = require('net'); 23 | var url = require('url'); 24 | var util = require('util'); 25 | var EventEmitter = require('events').EventEmitter; 26 | var ClientRequest = require('_http_client').ClientRequest; 27 | var debug = util.debuglog('http'); 28 | 29 | // New Agent code. 30 | 31 | // The largest departure from the previous implementation is that 32 | // an Agent instance holds connections for a variable number of host:ports. 33 | // Surprisingly, this is still API compatible as far as third parties are 34 | // concerned. The only code that really notices the difference is the 35 | // request object. 36 | 37 | // Another departure is that all code related to HTTP parsing is in 38 | // ClientRequest.onSocket(). The Agent is now *strictly* 39 | // concerned with managing a connection pool. 40 | 41 | function Agent(options) { 42 | if (!(this instanceof Agent)) 43 | return new Agent(options); 44 | 45 | EventEmitter.call(this); 46 | 47 | var self = this; 48 | 49 | self.defaultPort = 80; 50 | self.protocol = 'http:'; 51 | 52 | self.options = util._extend({}, options); 53 | 54 | // don't confuse net and make it think that we're connecting to a pipe 55 | self.options.path = null; 56 | self.requests = {}; 57 | self.sockets = {}; 58 | self.freeSockets = {}; 59 | self.keepAliveMsecs = self.options.keepAliveMsecs || 1000; 60 | self.keepAlive = self.options.keepAlive || false; 61 | self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets; 62 | self.maxFreeSockets = self.options.maxFreeSockets || 256; 63 | 64 | self.on('free', function(socket, options) { 65 | var name = self.getName(options); 66 | debug('agent.on(free)', name); 67 | 68 | if (!socket.destroyed && 69 | self.requests[name] && self.requests[name].length) { 70 | self.requests[name].shift().onSocket(socket); 71 | if (self.requests[name].length === 0) { 72 | // don't leak 73 | delete self.requests[name]; 74 | } 75 | } else { 76 | // If there are no pending requests, then put it in 77 | // the freeSockets pool, but only if we're allowed to do so. 78 | var req = socket._httpMessage; 79 | if (req && 80 | req.shouldKeepAlive && 81 | !socket.destroyed && 82 | self.options.keepAlive) { 83 | var freeSockets = self.freeSockets[name]; 84 | var freeLen = freeSockets ? freeSockets.length : 0; 85 | var count = freeLen; 86 | if (self.sockets[name]) 87 | count += self.sockets[name].length; 88 | 89 | if (count >= self.maxSockets || freeLen >= self.maxFreeSockets) { 90 | self.removeSocket(socket, options); 91 | socket.destroy(); 92 | } else { 93 | freeSockets = freeSockets || []; 94 | self.freeSockets[name] = freeSockets; 95 | socket.setKeepAlive(true, self.keepAliveMsecs); 96 | socket.unref(); 97 | socket._httpMessage = null; 98 | self.removeSocket(socket, options); 99 | freeSockets.push(socket); 100 | } 101 | } else { 102 | self.removeSocket(socket, options); 103 | socket.destroy(); 104 | } 105 | } 106 | }); 107 | } 108 | 109 | util.inherits(Agent, EventEmitter); 110 | exports.Agent = Agent; 111 | 112 | Agent.defaultMaxSockets = Infinity; 113 | 114 | Agent.prototype.createConnection = net.createConnection; 115 | 116 | // Get the key for a given set of request options 117 | Agent.prototype.getName = function(options) { 118 | var name = ''; 119 | 120 | if (options.host) 121 | name += options.host; 122 | else 123 | name += 'localhost'; 124 | 125 | name += ':'; 126 | if (options.port) 127 | name += options.port; 128 | name += ':'; 129 | if (options.localAddress) 130 | name += options.localAddress; 131 | name += ':'; 132 | return name; 133 | }; 134 | 135 | Agent.prototype.addRequest = function(req, options) { 136 | // Legacy API: addRequest(req, host, port, path) 137 | if (typeof options === 'string') { 138 | options = { 139 | host: options, 140 | port: arguments[2], 141 | path: arguments[3] 142 | }; 143 | } 144 | 145 | var name = this.getName(options); 146 | if (!this.sockets[name]) { 147 | this.sockets[name] = []; 148 | } 149 | 150 | var freeLen = this.freeSockets[name] ? this.freeSockets[name].length : 0; 151 | var sockLen = freeLen + this.sockets[name].length; 152 | 153 | if (freeLen) { 154 | // we have a free socket, so use that. 155 | var socket = this.freeSockets[name].shift(); 156 | debug('have free socket'); 157 | 158 | // don't leak 159 | if (!this.freeSockets[name].length) 160 | delete this.freeSockets[name]; 161 | 162 | socket.ref(); 163 | req.onSocket(socket); 164 | this.sockets[name].push(socket); 165 | } else if (sockLen < this.maxSockets) { 166 | debug('call onSocket', sockLen, freeLen); 167 | // If we are under maxSockets create a new one. 168 | req.onSocket(this.createSocket(req, options)); 169 | } else { 170 | debug('wait for socket'); 171 | // We are over limit so we'll add it to the queue. 172 | if (!this.requests[name]) { 173 | this.requests[name] = []; 174 | } 175 | this.requests[name].push(req); 176 | } 177 | }; 178 | 179 | Agent.prototype.createSocket = function(req, options) { 180 | var self = this; 181 | options = util._extend({}, options); 182 | options = util._extend(options, self.options); 183 | 184 | options.servername = options.host; 185 | if (req) { 186 | var hostHeader = req.getHeader('host'); 187 | if (hostHeader) { 188 | options.servername = hostHeader.replace(/:.*$/, ''); 189 | } 190 | } 191 | 192 | var name = self.getName(options); 193 | 194 | debug('createConnection', name, options); 195 | options.encoding = null; 196 | var s = self.createConnection(options); 197 | if (!self.sockets[name]) { 198 | self.sockets[name] = []; 199 | } 200 | this.sockets[name].push(s); 201 | debug('sockets', name, this.sockets[name].length); 202 | 203 | function onFree() { 204 | self.emit('free', s, options); 205 | } 206 | s.on('free', onFree); 207 | 208 | function onClose(err) { 209 | debug('CLIENT socket onClose'); 210 | // This is the only place where sockets get removed from the Agent. 211 | // If you want to remove a socket from the pool, just close it. 212 | // All socket errors end in a close event anyway. 213 | self.removeSocket(s, options); 214 | } 215 | s.on('close', onClose); 216 | 217 | function onRemove() { 218 | // We need this function for cases like HTTP 'upgrade' 219 | // (defined by WebSockets) where we need to remove a socket from the 220 | // pool because it'll be locked up indefinitely 221 | debug('CLIENT socket onRemove'); 222 | self.removeSocket(s, options); 223 | s.removeListener('close', onClose); 224 | s.removeListener('free', onFree); 225 | s.removeListener('agentRemove', onRemove); 226 | } 227 | s.on('agentRemove', onRemove); 228 | return s; 229 | }; 230 | 231 | Agent.prototype.removeSocket = function(s, options) { 232 | var name = this.getName(options); 233 | debug('removeSocket', name, 'destroyed:', s.destroyed); 234 | var sets = [this.sockets]; 235 | 236 | // If the socket was destroyed, remove it from the free buffers too. 237 | if (s.destroyed) 238 | sets.push(this.freeSockets); 239 | 240 | sets.forEach(function(sockets) { 241 | if (sockets[name]) { 242 | var index = sockets[name].indexOf(s); 243 | if (index !== -1) { 244 | sockets[name].splice(index, 1); 245 | // Don't leak 246 | if (sockets[name].length === 0) 247 | delete sockets[name]; 248 | } 249 | } 250 | }); 251 | if (this.requests[name] && this.requests[name].length) { 252 | debug('removeSocket, have a request, make a socket'); 253 | var req = this.requests[name][0]; 254 | // If we have pending requests and a socket gets closed make a new one 255 | this.createSocket(req, options).emit('free'); 256 | } 257 | }; 258 | 259 | Agent.prototype.destroy = function() { 260 | var sets = [this.freeSockets, this.sockets]; 261 | sets.forEach(function(set) { 262 | Object.keys(set).forEach(function(name) { 263 | set[name].forEach(function(socket) { 264 | socket.destroy(); 265 | }); 266 | }); 267 | }); 268 | }; 269 | 270 | Agent.prototype.request = function(options, cb) { 271 | if (util.isString(options)) { 272 | options = url.parse(options); 273 | } 274 | // don't try to do dns lookups of foo.com:8080, just foo.com 275 | if (options.hostname) { 276 | options.host = options.hostname; 277 | } 278 | 279 | if (options && options.path && / /.test(options.path)) { 280 | // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ 281 | // with an additional rule for ignoring percentage-escaped characters 282 | // but that's a) hard to capture in a regular expression that performs 283 | // well, and b) possibly too restrictive for real-world usage. That's 284 | // why it only scans for spaces because those are guaranteed to create 285 | // an invalid request. 286 | throw new TypeError('Request path contains unescaped characters.'); 287 | } else if (options.protocol && options.protocol !== this.protocol) { 288 | throw new Error('Protocol:' + options.protocol + ' not supported.'); 289 | } 290 | 291 | options = util._extend({ 292 | agent: this, 293 | keepAlive: this.keepAlive 294 | }, options); 295 | 296 | // if it's false, then make a new one, just like this one. 297 | if (options.agent === false) 298 | options.agent = new this.constructor(); 299 | 300 | debug('agent.request', options); 301 | return new ClientRequest(options, cb); 302 | }; 303 | 304 | Agent.prototype.get = function(options, cb) { 305 | var req = this.request(options, cb); 306 | req.end(); 307 | return req; 308 | }; 309 | 310 | exports.globalAgent = new Agent(); 311 | -------------------------------------------------------------------------------- /commonjs/lib/_http_common.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var FreeList = require('freelist').FreeList; 23 | var HTTPParser = process.binding('http_parser').HTTPParser; 24 | 25 | var incoming = require('_http_incoming'); 26 | var IncomingMessage = incoming.IncomingMessage; 27 | var readStart = incoming.readStart; 28 | var readStop = incoming.readStop; 29 | 30 | var isNumber = require('util').isNumber; 31 | var debug = require('util').debuglog('http'); 32 | exports.debug = debug; 33 | 34 | exports.CRLF = '\r\n'; 35 | exports.chunkExpression = /chunk/i; 36 | exports.continueExpression = /100-continue/i; 37 | exports.methods = HTTPParser.methods; 38 | 39 | var kOnHeaders = HTTPParser.kOnHeaders | 0; 40 | var kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0; 41 | var kOnBody = HTTPParser.kOnBody | 0; 42 | var kOnMessageComplete = HTTPParser.kOnMessageComplete | 0; 43 | 44 | // Only called in the slow case where slow means 45 | // that the request headers were either fragmented 46 | // across multiple TCP packets or too large to be 47 | // processed in a single run. This method is also 48 | // called to process trailing HTTP headers. 49 | function parserOnHeaders(headers, url) { 50 | // Once we exceeded headers limit - stop collecting them 51 | if (this.maxHeaderPairs <= 0 || 52 | this._headers.length < this.maxHeaderPairs) { 53 | this._headers = this._headers.concat(headers); 54 | } 55 | this._url += url; 56 | } 57 | 58 | // info.headers and info.url are set only if .onHeaders() 59 | // has not been called for this request. 60 | // 61 | // info.url is not set for response parsers but that's not 62 | // applicable here since all our parsers are request parsers. 63 | function parserOnHeadersComplete(info) { 64 | debug('parserOnHeadersComplete', info); 65 | var parser = this; 66 | var headers = info.headers; 67 | var url = info.url; 68 | 69 | if (!headers) { 70 | headers = parser._headers; 71 | parser._headers = []; 72 | } 73 | 74 | if (!url) { 75 | url = parser._url; 76 | parser._url = ''; 77 | } 78 | 79 | parser.incoming = new IncomingMessage(parser.socket); 80 | parser.incoming.httpVersionMajor = info.versionMajor; 81 | parser.incoming.httpVersionMinor = info.versionMinor; 82 | parser.incoming.httpVersion = info.versionMajor + '.' + info.versionMinor; 83 | parser.incoming.url = url; 84 | 85 | var n = headers.length; 86 | 87 | // If parser.maxHeaderPairs <= 0 - assume that there're no limit 88 | if (parser.maxHeaderPairs > 0) { 89 | n = Math.min(n, parser.maxHeaderPairs); 90 | } 91 | 92 | parser.incoming._addHeaderLines(headers, n); 93 | 94 | if (isNumber(info.method)) { 95 | // server only 96 | parser.incoming.method = HTTPParser.methods[info.method]; 97 | } else { 98 | // client only 99 | parser.incoming.statusCode = info.statusCode; 100 | parser.incoming.statusMessage = info.statusMessage; 101 | } 102 | 103 | parser.incoming.upgrade = info.upgrade; 104 | 105 | var skipBody = false; // response to HEAD or CONNECT 106 | 107 | if (!info.upgrade) { 108 | // For upgraded connections and CONNECT method request, 109 | // we'll emit this after parser.execute 110 | // so that we can capture the first part of the new protocol 111 | skipBody = parser.onIncoming(parser.incoming, info.shouldKeepAlive); 112 | } 113 | 114 | return skipBody; 115 | } 116 | 117 | // XXX This is a mess. 118 | // TODO: http.Parser should be a Writable emits request/response events. 119 | function parserOnBody(b, start, len) { 120 | var parser = this; 121 | var stream = parser.incoming; 122 | 123 | // if the stream has already been removed, then drop it. 124 | if (!stream) 125 | return; 126 | 127 | var socket = stream.socket; 128 | 129 | // pretend this was the result of a stream._read call. 130 | if (len > 0 && !stream._dumped) { 131 | var slice = b.slice(start, start + len); 132 | var ret = stream.push(slice); 133 | if (!ret) 134 | readStop(socket); 135 | } 136 | } 137 | 138 | function parserOnMessageComplete() { 139 | var parser = this; 140 | var stream = parser.incoming; 141 | 142 | if (stream) { 143 | stream.complete = true; 144 | // Emit any trailing headers. 145 | var headers = parser._headers; 146 | if (headers) { 147 | parser.incoming._addHeaderLines(headers, headers.length); 148 | parser._headers = []; 149 | parser._url = ''; 150 | } 151 | 152 | if (!stream.upgrade) 153 | // For upgraded connections, also emit this after parser.execute 154 | stream.push(null); 155 | } 156 | 157 | if (stream && !parser.incoming._pendings.length) { 158 | // For emit end event 159 | stream.push(null); 160 | } 161 | 162 | // force to read the next incoming message 163 | readStart(parser.socket); 164 | } 165 | 166 | 167 | var parsers = new FreeList('parsers', 1000, function() { 168 | var parser = new HTTPParser(HTTPParser.REQUEST); 169 | 170 | parser._headers = []; 171 | parser._url = ''; 172 | 173 | // Only called in the slow case where slow means 174 | // that the request headers were either fragmented 175 | // across multiple TCP packets or too large to be 176 | // processed in a single run. This method is also 177 | // called to process trailing HTTP headers. 178 | parser[kOnHeaders] = parserOnHeaders; 179 | parser[kOnHeadersComplete] = parserOnHeadersComplete; 180 | parser[kOnBody] = parserOnBody; 181 | parser[kOnMessageComplete] = parserOnMessageComplete; 182 | 183 | return parser; 184 | }); 185 | exports.parsers = parsers; 186 | 187 | 188 | // Free the parser and also break any links that it 189 | // might have to any other things. 190 | // TODO: All parser data should be attached to a 191 | // single object, so that it can be easily cleaned 192 | // up by doing `parser.data = {}`, which should 193 | // be done in FreeList.free. `parsers.free(parser)` 194 | // should be all that is needed. 195 | function freeParser(parser, req) { 196 | if (parser) { 197 | parser._headers = []; 198 | parser.onIncoming = null; 199 | if (parser.socket) 200 | parser.socket.parser = null; 201 | parser.socket = null; 202 | parser.incoming = null; 203 | parsers.free(parser); 204 | parser = null; 205 | } 206 | if (req) { 207 | req.parser = null; 208 | } 209 | } 210 | exports.freeParser = freeParser; 211 | 212 | 213 | function ondrain() { 214 | if (this._httpMessage) this._httpMessage.emit('drain'); 215 | } 216 | 217 | 218 | function httpSocketSetup(socket) { 219 | socket.removeListener('drain', ondrain); 220 | socket.on('drain', ondrain); 221 | } 222 | exports.httpSocketSetup = httpSocketSetup; 223 | -------------------------------------------------------------------------------- /commonjs/lib/_http_incoming.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var util = require('util'); 23 | var Stream = require('stream'); 24 | 25 | function readStart(socket) { 26 | if (socket && !socket._paused && socket.readable) 27 | socket.resume(); 28 | } 29 | exports.readStart = readStart; 30 | 31 | function readStop(socket) { 32 | if (socket) 33 | socket.pause(); 34 | } 35 | exports.readStop = readStop; 36 | 37 | 38 | /* Abstract base class for ServerRequest and ClientResponse. */ 39 | function IncomingMessage(socket) { 40 | Stream.Readable.call(this); 41 | 42 | // XXX This implementation is kind of all over the place 43 | // When the parser emits body chunks, they go in this list. 44 | // _read() pulls them out, and when it finds EOF, it ends. 45 | 46 | this.socket = socket; 47 | this.connection = socket; 48 | 49 | this.httpVersion = null; 50 | this.complete = false; 51 | this.headers = {}; 52 | this.rawHeaders = []; 53 | this.trailers = {}; 54 | this.rawTrailers = []; 55 | 56 | this.readable = true; 57 | 58 | this._pendings = []; 59 | this._pendingIndex = 0; 60 | 61 | // request (server) only 62 | this.url = ''; 63 | this.method = null; 64 | 65 | // response (client) only 66 | this.statusCode = null; 67 | this.statusMessage = null; 68 | this.client = this.socket; 69 | 70 | // flag for backwards compatibility grossness. 71 | this._consuming = false; 72 | 73 | // flag for when we decide that this message cannot possibly be 74 | // read by the user, so there's no point continuing to handle it. 75 | this._dumped = false; 76 | } 77 | util.inherits(IncomingMessage, Stream.Readable); 78 | 79 | 80 | exports.IncomingMessage = IncomingMessage; 81 | 82 | 83 | IncomingMessage.prototype.setTimeout = function(msecs, callback) { 84 | if (callback) 85 | this.on('timeout', callback); 86 | this.socket.setTimeout(msecs); 87 | }; 88 | 89 | 90 | IncomingMessage.prototype.read = function(n) { 91 | this._consuming = true; 92 | this.read = Stream.Readable.prototype.read; 93 | return this.read(n); 94 | }; 95 | 96 | 97 | IncomingMessage.prototype._read = function(n) { 98 | // We actually do almost nothing here, because the parserOnBody 99 | // function fills up our internal buffer directly. However, we 100 | // do need to unpause the underlying socket so that it flows. 101 | if (!this.socket.readable) 102 | this.push(null); 103 | else 104 | readStart(this.socket); 105 | }; 106 | 107 | 108 | // It's possible that the socket will be destroyed, and removed from 109 | // any messages, before ever calling this. In that case, just skip 110 | // it, since something else is destroying this connection anyway. 111 | IncomingMessage.prototype.destroy = function(error) { 112 | if (this.socket) 113 | this.socket.destroy(error); 114 | }; 115 | 116 | 117 | IncomingMessage.prototype._addHeaderLines = function(headers, n) { 118 | if (headers && headers.length) { 119 | var raw, dest; 120 | if (this.complete) { 121 | raw = this.rawTrailers; 122 | dest = this.trailers; 123 | } else { 124 | raw = this.rawHeaders; 125 | dest = this.headers; 126 | } 127 | raw.push.apply(raw, headers); 128 | 129 | for (var i = 0; i < n; i += 2) { 130 | var k = headers[i]; 131 | var v = headers[i + 1]; 132 | this._addHeaderLine(k, v, dest); 133 | } 134 | } 135 | }; 136 | 137 | 138 | // Add the given (field, value) pair to the message 139 | // 140 | // Per RFC2616, section 4.2 it is acceptable to join multiple instances of the 141 | // same header with a ', ' if the header in question supports specification of 142 | // multiple values this way. If not, we declare the first instance the winner 143 | // and drop the second. Extended header fields (those beginning with 'x-') are 144 | // always joined. 145 | IncomingMessage.prototype._addHeaderLine = function(field, value, dest) { 146 | field = field.toLowerCase(); 147 | switch (field) { 148 | // Array headers: 149 | case 'set-cookie': 150 | if (!util.isUndefined(dest[field])) { 151 | dest[field].push(value); 152 | } else { 153 | dest[field] = [value]; 154 | } 155 | break; 156 | 157 | // Comma separate. Maybe make these arrays? 158 | case 'accept': 159 | case 'accept-charset': 160 | case 'accept-encoding': 161 | case 'accept-language': 162 | case 'connection': 163 | case 'cookie': 164 | case 'pragma': 165 | case 'link': 166 | case 'www-authenticate': 167 | case 'proxy-authenticate': 168 | case 'sec-websocket-extensions': 169 | case 'sec-websocket-protocol': 170 | if (!util.isUndefined(dest[field])) { 171 | dest[field] += ', ' + value; 172 | } else { 173 | dest[field] = value; 174 | } 175 | break; 176 | 177 | 178 | default: 179 | if (field.slice(0, 2) == 'x-') { 180 | // except for x- 181 | if (!util.isUndefined(dest[field])) { 182 | dest[field] += ', ' + value; 183 | } else { 184 | dest[field] = value; 185 | } 186 | } else { 187 | // drop duplicates 188 | if (util.isUndefined(dest[field])) dest[field] = value; 189 | } 190 | break; 191 | } 192 | }; 193 | 194 | 195 | // Call this instead of resume() if we want to just 196 | // dump all the data to /dev/null 197 | IncomingMessage.prototype._dump = function() { 198 | if (!this._dumped) { 199 | this._dumped = true; 200 | this.resume(); 201 | } 202 | }; 203 | -------------------------------------------------------------------------------- /commonjs/lib/_linklist.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | function init(list) { 23 | list._idleNext = list; 24 | list._idlePrev = list; 25 | } 26 | exports.init = init; 27 | 28 | 29 | // show the most idle item 30 | function peek(list) { 31 | if (list._idlePrev == list) return null; 32 | return list._idlePrev; 33 | } 34 | exports.peek = peek; 35 | 36 | 37 | // remove the most idle item from the list 38 | function shift(list) { 39 | var first = list._idlePrev; 40 | remove(first); 41 | return first; 42 | } 43 | exports.shift = shift; 44 | 45 | 46 | // remove a item from its list 47 | function remove(item) { 48 | if (item._idleNext) { 49 | item._idleNext._idlePrev = item._idlePrev; 50 | } 51 | 52 | if (item._idlePrev) { 53 | item._idlePrev._idleNext = item._idleNext; 54 | } 55 | 56 | item._idleNext = null; 57 | item._idlePrev = null; 58 | } 59 | exports.remove = remove; 60 | 61 | 62 | // remove a item from its list and place at the end. 63 | function append(list, item) { 64 | remove(item); 65 | item._idleNext = list._idleNext; 66 | list._idleNext._idlePrev = item; 67 | item._idlePrev = list; 68 | list._idleNext = item; 69 | } 70 | exports.append = append; 71 | 72 | 73 | function isEmpty(list) { 74 | return list._idleNext === list; 75 | } 76 | exports.isEmpty = isEmpty; 77 | -------------------------------------------------------------------------------- /commonjs/lib/_stream_duplex.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // a duplex stream is just a stream that is both readable and writable. 23 | // Since JS doesn't have multiple prototypal inheritance, this class 24 | // prototypally inherits from Readable, and then parasitically from 25 | // Writable. 26 | 27 | module.exports = Duplex; 28 | var util = require('util'); 29 | var Readable = require('_stream_readable'); 30 | var Writable = require('_stream_writable'); 31 | 32 | util.inherits(Duplex, Readable); 33 | 34 | Object.keys(Writable.prototype).forEach(function(method) { 35 | if (!Duplex.prototype[method]) 36 | Duplex.prototype[method] = Writable.prototype[method]; 37 | }); 38 | 39 | function Duplex(options) { 40 | if (!(this instanceof Duplex)) 41 | return new Duplex(options); 42 | 43 | Readable.call(this, options); 44 | Writable.call(this, options); 45 | 46 | if (options && options.readable === false) 47 | this.readable = false; 48 | 49 | if (options && options.writable === false) 50 | this.writable = false; 51 | 52 | this.allowHalfOpen = true; 53 | if (options && options.allowHalfOpen === false) 54 | this.allowHalfOpen = false; 55 | 56 | this.once('end', onend); 57 | } 58 | 59 | // the no-half-open enforcer 60 | function onend() { 61 | // if we allow half-open state, or if the writable side ended, 62 | // then we're ok. 63 | if (this.allowHalfOpen || this._writableState.ended) 64 | return; 65 | 66 | // no more data can be written. 67 | // But allow more writes to happen in this tick. 68 | process.nextTick(this.end.bind(this)); 69 | } 70 | -------------------------------------------------------------------------------- /commonjs/lib/_stream_passthrough.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // a passthrough stream. 23 | // basically just the most minimal sort of Transform stream. 24 | // Every written chunk gets output as-is. 25 | 26 | module.exports = PassThrough; 27 | 28 | var Transform = require('_stream_transform'); 29 | var util = require('util'); 30 | util.inherits(PassThrough, Transform); 31 | 32 | function PassThrough(options) { 33 | if (!(this instanceof PassThrough)) 34 | return new PassThrough(options); 35 | 36 | Transform.call(this, options); 37 | } 38 | 39 | PassThrough.prototype._transform = function(chunk, encoding, cb) { 40 | cb(null, chunk); 41 | }; 42 | -------------------------------------------------------------------------------- /commonjs/lib/_stream_transform.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | // a transform stream is a readable/writable stream where you do 24 | // something with the data. Sometimes it's called a "filter", 25 | // but that's not a great name for it, since that implies a thing where 26 | // some bits pass through, and others are simply ignored. (That would 27 | // be a valid example of a transform, of course.) 28 | // 29 | // While the output is causally related to the input, it's not a 30 | // necessarily symmetric or synchronous transformation. For example, 31 | // a zlib stream might take multiple plain-text writes(), and then 32 | // emit a single compressed chunk some time in the future. 33 | // 34 | // Here's how this works: 35 | // 36 | // The Transform stream has all the aspects of the readable and writable 37 | // stream classes. When you write(chunk), that calls _write(chunk,cb) 38 | // internally, and returns false if there's a lot of pending writes 39 | // buffered up. When you call read(), that calls _read(n) until 40 | // there's enough pending readable data buffered up. 41 | // 42 | // In a transform stream, the written data is placed in a buffer. When 43 | // _read(n) is called, it transforms the queued up data, calling the 44 | // buffered _write cb's as it consumes chunks. If consuming a single 45 | // written chunk would result in multiple output chunks, then the first 46 | // outputted bit calls the readcb, and subsequent chunks just go into 47 | // the read buffer, and will cause it to emit 'readable' if necessary. 48 | // 49 | // This way, back-pressure is actually determined by the reading side, 50 | // since _read has to be called to start processing a new chunk. However, 51 | // a pathological inflate type of transform can cause excessive buffering 52 | // here. For example, imagine a stream where every byte of input is 53 | // interpreted as an integer from 0-255, and then results in that many 54 | // bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in 55 | // 1kb of data being output. In this case, you could write a very small 56 | // amount of input, and end up with a very large amount of output. In 57 | // such a pathological inflating mechanism, there'd be no way to tell 58 | // the system to stop doing the transform. A single 4MB write could 59 | // cause the system to run out of memory. 60 | // 61 | // However, even in such a pathological case, only a single written chunk 62 | // would be consumed, and then the rest would wait (un-transformed) until 63 | // the results of the previous transformed chunk were consumed. 64 | 65 | module.exports = Transform; 66 | 67 | var Duplex = require('_stream_duplex'); 68 | var util = require('util'); 69 | util.inherits(Transform, Duplex); 70 | 71 | 72 | function TransformState(options, stream) { 73 | this.afterTransform = function(er, data) { 74 | return afterTransform(stream, er, data); 75 | }; 76 | 77 | this.needTransform = false; 78 | this.transforming = false; 79 | this.writecb = null; 80 | this.writechunk = null; 81 | } 82 | 83 | function afterTransform(stream, er, data) { 84 | var ts = stream._transformState; 85 | ts.transforming = false; 86 | 87 | var cb = ts.writecb; 88 | 89 | if (!cb) 90 | return stream.emit('error', new Error('no writecb in Transform class')); 91 | 92 | ts.writechunk = null; 93 | ts.writecb = null; 94 | 95 | if (!util.isNullOrUndefined(data)) 96 | stream.push(data); 97 | 98 | if (cb) 99 | cb(er); 100 | 101 | var rs = stream._readableState; 102 | rs.reading = false; 103 | if (rs.needReadable || rs.length < rs.highWaterMark) { 104 | stream._read(rs.highWaterMark); 105 | } 106 | } 107 | 108 | 109 | function Transform(options) { 110 | if (!(this instanceof Transform)) 111 | return new Transform(options); 112 | 113 | Duplex.call(this, options); 114 | 115 | this._transformState = new TransformState(options, this); 116 | 117 | // when the writable side finishes, then flush out anything remaining. 118 | var stream = this; 119 | 120 | // start out asking for a readable event once data is transformed. 121 | this._readableState.needReadable = true; 122 | 123 | // we have implemented the _read method, and done the other things 124 | // that Readable wants before the first _read call, so unset the 125 | // sync guard flag. 126 | this._readableState.sync = false; 127 | 128 | this.once('prefinish', function() { 129 | if (util.isFunction(this._flush)) 130 | this._flush(function(er) { 131 | done(stream, er); 132 | }); 133 | else 134 | done(stream); 135 | }); 136 | } 137 | 138 | Transform.prototype.push = function(chunk, encoding) { 139 | this._transformState.needTransform = false; 140 | return Duplex.prototype.push.call(this, chunk, encoding); 141 | }; 142 | 143 | // This is the part where you do stuff! 144 | // override this function in implementation classes. 145 | // 'chunk' is an input chunk. 146 | // 147 | // Call `push(newChunk)` to pass along transformed output 148 | // to the readable side. You may call 'push' zero or more times. 149 | // 150 | // Call `cb(err)` when you are done with this chunk. If you pass 151 | // an error, then that'll put the hurt on the whole operation. If you 152 | // never call cb(), then you'll never get another chunk. 153 | Transform.prototype._transform = function(chunk, encoding, cb) { 154 | throw new Error('not implemented'); 155 | }; 156 | 157 | Transform.prototype._write = function(chunk, encoding, cb) { 158 | var ts = this._transformState; 159 | ts.writecb = cb; 160 | ts.writechunk = chunk; 161 | ts.writeencoding = encoding; 162 | if (!ts.transforming) { 163 | var rs = this._readableState; 164 | if (ts.needTransform || 165 | rs.needReadable || 166 | rs.length < rs.highWaterMark) 167 | this._read(rs.highWaterMark); 168 | } 169 | }; 170 | 171 | // Doesn't matter what the args are here. 172 | // _transform does all the work. 173 | // That we got here means that the readable side wants more data. 174 | Transform.prototype._read = function(n) { 175 | var ts = this._transformState; 176 | 177 | if (!util.isNull(ts.writechunk) && ts.writecb && !ts.transforming) { 178 | ts.transforming = true; 179 | this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); 180 | } else { 181 | // mark that we need a transform, so that any data that comes in 182 | // will get processed, now that we've asked for it. 183 | ts.needTransform = true; 184 | } 185 | }; 186 | 187 | 188 | function done(stream, er) { 189 | if (er) 190 | return stream.emit('error', er); 191 | 192 | // if there's nothing in the write buffer, then that means 193 | // that nothing more will ever be provided 194 | var ws = stream._writableState; 195 | var ts = stream._transformState; 196 | 197 | if (ws.length) 198 | throw new Error('calling transform done when ws.length != 0'); 199 | 200 | if (ts.transforming) 201 | throw new Error('calling transform done when still transforming'); 202 | 203 | return stream.push(null); 204 | } 205 | -------------------------------------------------------------------------------- /commonjs/lib/_stream_writable.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // A bit simpler than readable streams. 23 | // Implement an async ._write(chunk, cb), and it'll handle all 24 | // the drain event emission and buffering. 25 | 26 | module.exports = Writable; 27 | Writable.WritableState = WritableState; 28 | 29 | var util = require('util'); 30 | var Stream = require('stream'); 31 | 32 | util.inherits(Writable, Stream); 33 | 34 | function WriteReq(chunk, encoding, cb) { 35 | this.chunk = chunk; 36 | this.encoding = encoding; 37 | this.callback = cb; 38 | } 39 | 40 | function WritableState(options, stream) { 41 | options = options || {}; 42 | 43 | // the point at which write() starts returning false 44 | // Note: 0 is a valid value, means that we always return false if 45 | // the entire buffer is not flushed immediately on write() 46 | var hwm = options.highWaterMark; 47 | var defaultHwm = options.objectMode ? 16 : 16 * 1024; 48 | this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; 49 | 50 | // object stream flag to indicate whether or not this stream 51 | // contains buffers or objects. 52 | this.objectMode = !!options.objectMode; 53 | 54 | // cast to ints. 55 | this.highWaterMark = ~~this.highWaterMark; 56 | 57 | this.needDrain = false; 58 | // at the start of calling end() 59 | this.ending = false; 60 | // when end() has been called, and returned 61 | this.ended = false; 62 | // when 'finish' is emitted 63 | this.finished = false; 64 | 65 | // should we decode strings into buffers before passing to _write? 66 | // this is here so that some node-core streams can optimize string 67 | // handling at a lower level. 68 | var noDecode = options.decodeStrings === false; 69 | this.decodeStrings = !noDecode; 70 | 71 | // Crypto is kind of old and crusty. Historically, its default string 72 | // encoding is 'binary' so we have to make this configurable. 73 | // Everything else in the universe uses 'utf8', though. 74 | this.defaultEncoding = options.defaultEncoding || 'utf8'; 75 | 76 | // not an actual buffer we keep track of, but a measurement 77 | // of how much we're waiting to get pushed to some underlying 78 | // socket or file. 79 | this.length = 0; 80 | 81 | // a flag to see when we're in the middle of a write. 82 | this.writing = false; 83 | 84 | // when true all writes will be buffered until .uncork() call 85 | this.corked = 0; 86 | 87 | // a flag to be able to tell if the onwrite cb is called immediately, 88 | // or on a later tick. We set this to true at first, because any 89 | // actions that shouldn't happen until "later" should generally also 90 | // not happen before the first write call. 91 | this.sync = true; 92 | 93 | // a flag to know if we're processing previously buffered items, which 94 | // may call the _write() callback in the same tick, so that we don't 95 | // end up in an overlapped onwrite situation. 96 | this.bufferProcessing = false; 97 | 98 | // the callback that's passed to _write(chunk,cb) 99 | this.onwrite = function(er) { 100 | onwrite(stream, er); 101 | }; 102 | 103 | // the callback that the user supplies to write(chunk,encoding,cb) 104 | this.writecb = null; 105 | 106 | // the amount that is being written when _write is called. 107 | this.writelen = 0; 108 | 109 | this.buffer = []; 110 | 111 | // number of pending user-supplied write callbacks 112 | // this must be 0 before 'finish' can be emitted 113 | this.pendingcb = 0; 114 | 115 | // emit prefinish if the only thing we're waiting for is _write cbs 116 | // This is relevant for synchronous Transform streams 117 | this.prefinished = false; 118 | } 119 | 120 | function Writable(options) { 121 | // Writable ctor is applied to Duplexes, though they're not 122 | // instanceof Writable, they're instanceof Readable. 123 | if (!(this instanceof Writable) && !(this instanceof Stream.Duplex)) 124 | return new Writable(options); 125 | 126 | this._writableState = new WritableState(options, this); 127 | 128 | // legacy. 129 | this.writable = true; 130 | 131 | Stream.call(this); 132 | } 133 | 134 | // Otherwise people can pipe Writable streams, which is just wrong. 135 | Writable.prototype.pipe = function() { 136 | this.emit('error', new Error('Cannot pipe. Not readable.')); 137 | }; 138 | 139 | 140 | function writeAfterEnd(stream, state, cb) { 141 | var er = new Error('write after end'); 142 | // TODO: defer error events consistently everywhere, not just the cb 143 | stream.emit('error', er); 144 | process.nextTick(function() { 145 | cb(er); 146 | }); 147 | } 148 | 149 | // If we get something that is not a buffer, string, null, or undefined, 150 | // and we're not in objectMode, then that's an error. 151 | // Otherwise stream chunks are all considered to be of length=1, and the 152 | // watermarks determine how many objects to keep in the buffer, rather than 153 | // how many bytes or characters. 154 | function validChunk(stream, state, chunk, cb) { 155 | var valid = true; 156 | if (!util.isBuffer(chunk) && 157 | !util.isString(chunk) && 158 | !util.isNullOrUndefined(chunk) && 159 | !state.objectMode) { 160 | var er = new TypeError('Invalid non-string/buffer chunk'); 161 | stream.emit('error', er); 162 | process.nextTick(function() { 163 | cb(er); 164 | }); 165 | valid = false; 166 | } 167 | return valid; 168 | } 169 | 170 | Writable.prototype.write = function(chunk, encoding, cb) { 171 | var state = this._writableState; 172 | var ret = false; 173 | 174 | if (util.isFunction(encoding)) { 175 | cb = encoding; 176 | encoding = null; 177 | } 178 | 179 | if (util.isBuffer(chunk)) 180 | encoding = 'buffer'; 181 | else if (!encoding) 182 | encoding = state.defaultEncoding; 183 | 184 | if (!util.isFunction(cb)) 185 | cb = function() {}; 186 | 187 | if (state.ended) 188 | writeAfterEnd(this, state, cb); 189 | else if (validChunk(this, state, chunk, cb)) { 190 | state.pendingcb++; 191 | ret = writeOrBuffer(this, state, chunk, encoding, cb); 192 | } 193 | 194 | return ret; 195 | }; 196 | 197 | Writable.prototype.cork = function() { 198 | var state = this._writableState; 199 | 200 | state.corked++; 201 | }; 202 | 203 | Writable.prototype.uncork = function() { 204 | var state = this._writableState; 205 | 206 | if (state.corked) { 207 | state.corked--; 208 | 209 | if (!state.writing && 210 | !state.corked && 211 | !state.finished && 212 | !state.bufferProcessing && 213 | state.buffer.length) 214 | clearBuffer(this, state); 215 | } 216 | }; 217 | 218 | function decodeChunk(state, chunk, encoding) { 219 | if (!state.objectMode && 220 | state.decodeStrings !== false && 221 | util.isString(chunk)) { 222 | chunk = new Buffer(chunk, encoding); 223 | } 224 | return chunk; 225 | } 226 | 227 | // if we're already writing something, then just put this 228 | // in the queue, and wait our turn. Otherwise, call _write 229 | // If we return false, then we need a drain event, so set that flag. 230 | function writeOrBuffer(stream, state, chunk, encoding, cb) { 231 | chunk = decodeChunk(state, chunk, encoding); 232 | if (util.isBuffer(chunk)) 233 | encoding = 'buffer'; 234 | var len = state.objectMode ? 1 : chunk.length; 235 | 236 | state.length += len; 237 | 238 | var ret = state.length < state.highWaterMark; 239 | state.needDrain = !ret; 240 | 241 | if (state.writing || state.corked) 242 | state.buffer.push(new WriteReq(chunk, encoding, cb)); 243 | else 244 | doWrite(stream, state, false, len, chunk, encoding, cb); 245 | 246 | return ret; 247 | } 248 | 249 | function doWrite(stream, state, writev, len, chunk, encoding, cb) { 250 | state.writelen = len; 251 | state.writecb = cb; 252 | state.writing = true; 253 | state.sync = true; 254 | if (writev) 255 | stream._writev(chunk, state.onwrite); 256 | else 257 | stream._write(chunk, encoding, state.onwrite); 258 | state.sync = false; 259 | } 260 | 261 | function onwriteError(stream, state, sync, er, cb) { 262 | if (sync) 263 | process.nextTick(function() { 264 | state.pendingcb--; 265 | cb(er); 266 | }); 267 | else { 268 | state.pendingcb--; 269 | cb(er); 270 | } 271 | 272 | stream.emit('error', er); 273 | } 274 | 275 | function onwriteStateUpdate(state) { 276 | state.writing = false; 277 | state.writecb = null; 278 | state.length -= state.writelen; 279 | state.writelen = 0; 280 | } 281 | 282 | function onwrite(stream, er) { 283 | var state = stream._writableState; 284 | var sync = state.sync; 285 | var cb = state.writecb; 286 | 287 | onwriteStateUpdate(state); 288 | 289 | if (er) 290 | onwriteError(stream, state, sync, er, cb); 291 | else { 292 | // Check if we're actually ready to finish, but don't emit yet 293 | var finished = needFinish(stream, state); 294 | 295 | if (!finished && 296 | !state.corked && 297 | !state.bufferProcessing && 298 | state.buffer.length) { 299 | clearBuffer(stream, state); 300 | } 301 | 302 | if (sync) { 303 | process.nextTick(function() { 304 | afterWrite(stream, state, finished, cb); 305 | }); 306 | } else { 307 | afterWrite(stream, state, finished, cb); 308 | } 309 | } 310 | } 311 | 312 | function afterWrite(stream, state, finished, cb) { 313 | if (!finished) 314 | onwriteDrain(stream, state); 315 | state.pendingcb--; 316 | cb(); 317 | finishMaybe(stream, state); 318 | } 319 | 320 | // Must force callback to be called on nextTick, so that we don't 321 | // emit 'drain' before the write() consumer gets the 'false' return 322 | // value, and has a chance to attach a 'drain' listener. 323 | function onwriteDrain(stream, state) { 324 | if (state.length === 0 && state.needDrain) { 325 | state.needDrain = false; 326 | stream.emit('drain'); 327 | } 328 | } 329 | 330 | 331 | // if there's something in the buffer waiting, then process it 332 | function clearBuffer(stream, state) { 333 | state.bufferProcessing = true; 334 | 335 | if (stream._writev && state.buffer.length > 1) { 336 | // Fast case, write everything using _writev() 337 | var cbs = []; 338 | for (var c = 0; c < state.buffer.length; c++) 339 | cbs.push(state.buffer[c].callback); 340 | 341 | // count the one we are adding, as well. 342 | // TODO(isaacs) clean this up 343 | state.pendingcb++; 344 | doWrite(stream, state, true, state.length, state.buffer, '', function(err) { 345 | for (var i = 0; i < cbs.length; i++) { 346 | state.pendingcb--; 347 | cbs[i](err); 348 | } 349 | }); 350 | 351 | // Clear buffer 352 | state.buffer = []; 353 | } else { 354 | // Slow case, write chunks one-by-one 355 | for (var c = 0; c < state.buffer.length; c++) { 356 | var entry = state.buffer[c]; 357 | var chunk = entry.chunk; 358 | var encoding = entry.encoding; 359 | var cb = entry.callback; 360 | var len = state.objectMode ? 1 : chunk.length; 361 | 362 | doWrite(stream, state, false, len, chunk, encoding, cb); 363 | 364 | // if we didn't call the onwrite immediately, then 365 | // it means that we need to wait until it does. 366 | // also, that means that the chunk and cb are currently 367 | // being processed, so move the buffer counter past them. 368 | if (state.writing) { 369 | c++; 370 | break; 371 | } 372 | } 373 | 374 | if (c < state.buffer.length) 375 | state.buffer = state.buffer.slice(c); 376 | else 377 | state.buffer.length = 0; 378 | } 379 | 380 | state.bufferProcessing = false; 381 | } 382 | 383 | Writable.prototype._write = function(chunk, encoding, cb) { 384 | cb(new Error('not implemented')); 385 | 386 | }; 387 | 388 | Writable.prototype._writev = null; 389 | 390 | Writable.prototype.end = function(chunk, encoding, cb) { 391 | var state = this._writableState; 392 | 393 | if (util.isFunction(chunk)) { 394 | cb = chunk; 395 | chunk = null; 396 | encoding = null; 397 | } else if (util.isFunction(encoding)) { 398 | cb = encoding; 399 | encoding = null; 400 | } 401 | 402 | if (!util.isNullOrUndefined(chunk)) 403 | this.write(chunk, encoding); 404 | 405 | // .end() fully uncorks 406 | if (state.corked) { 407 | state.corked = 1; 408 | this.uncork(); 409 | } 410 | 411 | // ignore unnecessary end() calls. 412 | if (!state.ending && !state.finished) 413 | endWritable(this, state, cb); 414 | }; 415 | 416 | 417 | function needFinish(stream, state) { 418 | return (state.ending && 419 | state.length === 0 && 420 | !state.finished && 421 | !state.writing); 422 | } 423 | 424 | function prefinish(stream, state) { 425 | if (!state.prefinished) { 426 | state.prefinished = true; 427 | stream.emit('prefinish'); 428 | } 429 | } 430 | 431 | function finishMaybe(stream, state) { 432 | var need = needFinish(stream, state); 433 | if (need) { 434 | if (state.pendingcb === 0) { 435 | prefinish(stream, state); 436 | state.finished = true; 437 | stream.emit('finish'); 438 | } else 439 | prefinish(stream, state); 440 | } 441 | return need; 442 | } 443 | 444 | function endWritable(stream, state, cb) { 445 | state.ending = true; 446 | finishMaybe(stream, state); 447 | if (cb) { 448 | if (state.finished) 449 | process.nextTick(cb); 450 | else 451 | stream.once('finish', cb); 452 | } 453 | state.ended = true; 454 | } 455 | -------------------------------------------------------------------------------- /commonjs/lib/assert.js: -------------------------------------------------------------------------------- 1 | // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 2 | // 3 | // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! 4 | // 5 | // Originally from narwhal.js (http://narwhaljs.org) 6 | // Copyright (c) 2009 Thomas Robinson <280north.com> 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the 'Software'), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | // UTILITY 26 | var util = require('util'); 27 | var pSlice = Array.prototype.slice; 28 | 29 | // 1. The assert module provides functions that throw 30 | // AssertionError's when particular conditions are not met. The 31 | // assert module must conform to the following interface. 32 | 33 | var assert = module.exports = ok; 34 | 35 | // 2. The AssertionError is defined in assert. 36 | // new assert.AssertionError({ message: message, 37 | // actual: actual, 38 | // expected: expected }) 39 | 40 | assert.AssertionError = function AssertionError(options) { 41 | this.name = 'AssertionError'; 42 | this.actual = options.actual; 43 | this.expected = options.expected; 44 | this.operator = options.operator; 45 | if (options.message) { 46 | this.message = options.message; 47 | this.generatedMessage = false; 48 | } else { 49 | this.message = getMessage(this); 50 | this.generatedMessage = true; 51 | } 52 | 53 | // Unfortunately Qt doesn't allow Error.captureStackTrace like this: 54 | // 55 | // var stackStartFunction = options.stackStartFunction || fail; 56 | // Error.captureStackTrace(this, stackStartFunction); 57 | // 58 | // So we use built-in console.tract instead. If you don't 59 | // want to see trace messages in your console you can disable 60 | // them globally via assert.AssertionError.silent = true 61 | // or when throwing error with silent: true option 62 | if(!assert.AssertionError.silent && !options.silent) { 63 | console.log(this); 64 | console.log('-- STACK TRACE --'); 65 | console.trace(); 66 | console.log('-- END TRACE --'); 67 | } 68 | }; 69 | 70 | // assert.AssertionError instanceof Error 71 | util.inherits(assert.AssertionError, Error); 72 | 73 | function replacer(key, value) { 74 | if (util.isUndefined(value)) { 75 | return '' + value; 76 | } 77 | if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) { 78 | return value.toString(); 79 | } 80 | if (util.isFunction(value) || util.isRegExp(value)) { 81 | return value.toString(); 82 | } 83 | return value; 84 | } 85 | 86 | function truncate(s, n) { 87 | if (util.isString(s)) { 88 | return s.length < n ? s : s.slice(0, n); 89 | } else { 90 | return s; 91 | } 92 | } 93 | 94 | function getMessage(self) { 95 | return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + 96 | self.operator + ' ' + 97 | truncate(JSON.stringify(self.expected, replacer), 128); 98 | } 99 | 100 | // At present only the three keys mentioned above are used and 101 | // understood by the spec. Implementations or sub modules can pass 102 | // other keys to the AssertionError's constructor - they will be 103 | // ignored. 104 | 105 | // 3. All of the following functions must throw an AssertionError 106 | // when a corresponding condition is not met, with a message that 107 | // may be undefined if not provided. All assertion methods provide 108 | // both the actual and expected values to the assertion error for 109 | // display purposes. 110 | 111 | function fail(actual, expected, message, operator, stackStartFunction) { 112 | throw new assert.AssertionError({ 113 | message: message, 114 | actual: actual, 115 | expected: expected, 116 | operator: operator, 117 | stackStartFunction: stackStartFunction 118 | }); 119 | } 120 | 121 | // EXTENSION! allows for well behaved errors defined elsewhere. 122 | assert.fail = fail; 123 | 124 | // 4. Pure assertion tests whether a value is truthy, as determined 125 | // by !!guard. 126 | // assert.ok(guard, message_opt); 127 | // This statement is equivalent to assert.equal(true, !!guard, 128 | // message_opt);. To test strictly for the value true, use 129 | // assert.strictEqual(true, guard, message_opt);. 130 | 131 | function ok(value, message) { 132 | if (!value) fail(value, true, message, '==', assert.ok); 133 | } 134 | assert.ok = ok; 135 | 136 | // 5. The equality assertion tests shallow, coercive equality with 137 | // ==. 138 | // assert.equal(actual, expected, message_opt); 139 | 140 | assert.equal = function equal(actual, expected, message) { 141 | if (actual != expected) fail(actual, expected, message, '==', assert.equal); 142 | }; 143 | 144 | // 6. The non-equality assertion tests for whether two objects are not equal 145 | // with != assert.notEqual(actual, expected, message_opt); 146 | 147 | assert.notEqual = function notEqual(actual, expected, message) { 148 | if (actual == expected) { 149 | fail(actual, expected, message, '!=', assert.notEqual); 150 | } 151 | }; 152 | 153 | // 7. The equivalence assertion tests a deep equality relation. 154 | // assert.deepEqual(actual, expected, message_opt); 155 | 156 | assert.deepEqual = function deepEqual(actual, expected, message) { 157 | if (!_deepEqual(actual, expected)) { 158 | fail(actual, expected, message, 'deepEqual', assert.deepEqual); 159 | } 160 | }; 161 | 162 | function _deepEqual(actual, expected) { 163 | // 7.1. All identical values are equivalent, as determined by ===. 164 | if (actual === expected) { 165 | return true; 166 | 167 | } else if (util.isBuffer(actual) && util.isBuffer(expected)) { 168 | if (actual.length != expected.length) return false; 169 | 170 | for (var i = 0; i < actual.length; i++) { 171 | if (actual[i] !== expected[i]) return false; 172 | } 173 | 174 | return true; 175 | 176 | // 7.2. If the expected value is a Date object, the actual value is 177 | // equivalent if it is also a Date object that refers to the same time. 178 | } else if (util.isDate(actual) && util.isDate(expected)) { 179 | return actual.getTime() === expected.getTime(); 180 | 181 | // 7.3 If the expected value is a RegExp object, the actual value is 182 | // equivalent if it is also a RegExp object with the same source and 183 | // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). 184 | } else if (util.isRegExp(actual) && util.isRegExp(expected)) { 185 | return actual.source === expected.source && 186 | actual.global === expected.global && 187 | actual.multiline === expected.multiline && 188 | actual.lastIndex === expected.lastIndex && 189 | actual.ignoreCase === expected.ignoreCase; 190 | 191 | // 7.4. Other pairs that do not both pass typeof value == 'object', 192 | // equivalence is determined by ==. 193 | } else if (!util.isObject(actual) && !util.isObject(expected)) { 194 | return actual == expected; 195 | 196 | // 7.5 For all other Object pairs, including Array objects, equivalence is 197 | // determined by having the same number of owned properties (as verified 198 | // with Object.prototype.hasOwnProperty.call), the same set of keys 199 | // (although not necessarily the same order), equivalent values for every 200 | // corresponding key, and an identical 'prototype' property. Note: this 201 | // accounts for both named and indexed properties on Arrays. 202 | } else { 203 | return objEquiv(actual, expected); 204 | } 205 | } 206 | 207 | function isArguments(object) { 208 | return Object.prototype.toString.call(object) == '[object Arguments]'; 209 | } 210 | 211 | function objEquiv(a, b) { 212 | if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) 213 | return false; 214 | // an identical 'prototype' property. 215 | if (a.prototype !== b.prototype) return false; 216 | //~~~I've managed to break Object.keys through screwy arguments passing. 217 | // Converting to array solves the problem. 218 | if (isArguments(a)) { 219 | if (!isArguments(b)) { 220 | return false; 221 | } 222 | a = pSlice.call(a); 223 | b = pSlice.call(b); 224 | return _deepEqual(a, b); 225 | } 226 | try { 227 | var ka = Object.keys(a), 228 | kb = Object.keys(b), 229 | key, i; 230 | } catch (e) {//happens when one is a string literal and the other isn't 231 | return false; 232 | } 233 | // having the same number of owned properties (keys incorporates 234 | // hasOwnProperty) 235 | if (ka.length != kb.length) 236 | return false; 237 | //the same set of keys (although not necessarily the same order), 238 | ka.sort(); 239 | kb.sort(); 240 | //~~~cheap key test 241 | for (i = ka.length - 1; i >= 0; i--) { 242 | if (ka[i] != kb[i]) 243 | return false; 244 | } 245 | //equivalent values for every corresponding key, and 246 | //~~~possibly expensive deep test 247 | for (i = ka.length - 1; i >= 0; i--) { 248 | key = ka[i]; 249 | if (!_deepEqual(a[key], b[key])) return false; 250 | } 251 | return true; 252 | } 253 | 254 | // 8. The non-equivalence assertion tests for any deep inequality. 255 | // assert.notDeepEqual(actual, expected, message_opt); 256 | 257 | assert.notDeepEqual = function notDeepEqual(actual, expected, message) { 258 | if (_deepEqual(actual, expected)) { 259 | fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); 260 | } 261 | }; 262 | 263 | // 9. The strict equality assertion tests strict equality, as determined by ===. 264 | // assert.strictEqual(actual, expected, message_opt); 265 | 266 | assert.strictEqual = function strictEqual(actual, expected, message) { 267 | if (actual !== expected) { 268 | fail(actual, expected, message, '===', assert.strictEqual); 269 | } 270 | }; 271 | 272 | // 10. The strict non-equality assertion tests for strict inequality, as 273 | // determined by !==. assert.notStrictEqual(actual, expected, message_opt); 274 | 275 | assert.notStrictEqual = function notStrictEqual(actual, expected, message) { 276 | if (actual === expected) { 277 | fail(actual, expected, message, '!==', assert.notStrictEqual); 278 | } 279 | }; 280 | 281 | function expectedException(actual, expected) { 282 | if (!actual || !expected) { 283 | return false; 284 | } 285 | 286 | if (Object.prototype.toString.call(expected) == '[object RegExp]') { 287 | return expected.test(actual); 288 | } else if (actual instanceof expected) { 289 | return true; 290 | } else if (expected.call({}, actual) === true) { 291 | return true; 292 | } 293 | 294 | return false; 295 | } 296 | 297 | function _throws(shouldThrow, block, expected, message) { 298 | var actual; 299 | 300 | if (util.isString(expected)) { 301 | message = expected; 302 | expected = null; 303 | } 304 | 305 | try { 306 | block(); 307 | } catch (e) { 308 | actual = e; 309 | } 310 | 311 | message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + 312 | (message ? ' ' + message : '.'); 313 | 314 | if (shouldThrow && !actual) { 315 | fail(actual, expected, 'Missing expected exception' + message); 316 | } 317 | 318 | if (!shouldThrow && expectedException(actual, expected)) { 319 | fail(actual, expected, 'Got unwanted exception' + message); 320 | } 321 | 322 | if ((shouldThrow && actual && expected && 323 | !expectedException(actual, expected)) || (!shouldThrow && actual)) { 324 | throw actual; 325 | } 326 | } 327 | 328 | // 11. Expected to throw an error: 329 | // assert.throws(block, Error_opt, message_opt); 330 | 331 | assert.throws = function(block, /*optional*/error, /*optional*/message) { 332 | _throws.apply(this, [true].concat(pSlice.call(arguments))); 333 | }; 334 | 335 | // EXTENSION! This is annoying to write outside this module. 336 | assert.doesNotThrow = function(block, /*optional*/message) { 337 | _throws.apply(this, [false].concat(pSlice.call(arguments))); 338 | }; 339 | 340 | assert.ifError = function(err) { if (err) {throw err;}}; 341 | -------------------------------------------------------------------------------- /commonjs/lib/console.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var util = require('util'); 23 | 24 | function Console(stdout, stderr) { 25 | if (!(this instanceof Console)) { 26 | return new Console(stdout, stderr); 27 | } 28 | if (!stdout || !util.isFunction(stdout.write)) { 29 | throw new TypeError('Console expects a writable stream instance'); 30 | } 31 | if (!stderr) { 32 | stderr = stdout; 33 | } 34 | var prop = { 35 | writable: true, 36 | enumerable: false, 37 | configurable: true 38 | }; 39 | prop.value = stdout; 40 | Object.defineProperty(this, '_stdout', prop); 41 | prop.value = stderr; 42 | Object.defineProperty(this, '_stderr', prop); 43 | prop.value = {}; 44 | Object.defineProperty(this, '_times', prop); 45 | 46 | // bind the prototype functions to this Console instance 47 | Object.keys(Console.prototype).forEach(function(k) { 48 | this[k] = this[k].bind(this); 49 | }, this); 50 | } 51 | 52 | Console.prototype.log = function() { 53 | this._stdout.write(util.format.apply(this, arguments) + '\n'); 54 | }; 55 | 56 | 57 | Console.prototype.info = Console.prototype.log; 58 | 59 | 60 | Console.prototype.warn = function() { 61 | this._stderr.write(util.format.apply(this, arguments) + '\n'); 62 | }; 63 | 64 | 65 | Console.prototype.error = Console.prototype.warn; 66 | 67 | 68 | Console.prototype.dir = function(object) { 69 | this._stdout.write(util.inspect(object, { customInspect: false }) + '\n'); 70 | }; 71 | 72 | 73 | Console.prototype.time = function(label) { 74 | this._times[label] = Date.now(); 75 | }; 76 | 77 | 78 | Console.prototype.timeEnd = function(label) { 79 | var time = this._times[label]; 80 | if (!time) { 81 | throw new Error('No such label: ' + label); 82 | } 83 | var duration = Date.now() - time; 84 | this.log('%s: %dms', label, duration); 85 | }; 86 | 87 | 88 | Console.prototype.trace = function() { 89 | // TODO probably can to do this better with V8's debug object once that is 90 | // exposed. 91 | var err = new Error; 92 | err.name = 'Trace'; 93 | err.message = util.format.apply(this, arguments); 94 | Error.captureStackTrace(err, arguments.callee); 95 | this.error(err.stack); 96 | }; 97 | 98 | 99 | Console.prototype.assert = function(expression) { 100 | if (!expression) { 101 | var arr = Array.prototype.slice.call(arguments, 1); 102 | require('assert').ok(false, util.format.apply(this, arr)); 103 | } 104 | }; 105 | 106 | 107 | module.exports = new Console(process.stdout, process.stderr); 108 | module.exports.Console = Console; 109 | -------------------------------------------------------------------------------- /commonjs/lib/constants.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | module.exports = process.binding('constants'); 23 | -------------------------------------------------------------------------------- /commonjs/lib/dgram.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var assert = require('assert'); 23 | var util = require('util'); 24 | var events = require('events'); 25 | 26 | var UDP = process.binding('udp_wrap').UDP; 27 | 28 | var BIND_STATE_UNBOUND = 0; 29 | var BIND_STATE_BINDING = 1; 30 | var BIND_STATE_BOUND = 2; 31 | 32 | // lazily loaded 33 | var cluster = null; 34 | var dns = null; 35 | 36 | var errnoException = util._errnoException; 37 | 38 | function lookup(address, family, callback) { 39 | if (!dns) 40 | dns = require('dns'); 41 | 42 | return dns.lookup(address, family, callback); 43 | } 44 | 45 | 46 | function lookup4(address, callback) { 47 | return lookup(address || '0.0.0.0', 4, callback); 48 | } 49 | 50 | 51 | function lookup6(address, callback) { 52 | return lookup(address || '::0', 6, callback); 53 | } 54 | 55 | 56 | function newHandle(type) { 57 | if (type == 'udp4') { 58 | var handle = new UDP; 59 | handle.lookup = lookup4; 60 | return handle; 61 | } 62 | 63 | if (type == 'udp6') { 64 | var handle = new UDP; 65 | handle.lookup = lookup6; 66 | handle.bind = handle.bind6; 67 | handle.send = handle.send6; 68 | return handle; 69 | } 70 | 71 | if (type == 'unix_dgram') 72 | throw new Error('unix_dgram sockets are not supported any more.'); 73 | 74 | throw new Error('Bad socket type specified. Valid types are: udp4, udp6'); 75 | } 76 | 77 | 78 | exports._createSocketHandle = function(address, port, addressType, fd) { 79 | // Opening an existing fd is not supported for UDP handles. 80 | assert(!util.isNumber(fd) || fd < 0); 81 | 82 | var handle = newHandle(addressType); 83 | 84 | if (port || address) { 85 | var err = handle.bind(address, port || 0, 0); 86 | if (err) { 87 | handle.close(); 88 | return err; 89 | } 90 | } 91 | 92 | return handle; 93 | }; 94 | 95 | 96 | function Socket(type, listener) { 97 | events.EventEmitter.call(this); 98 | 99 | var handle = newHandle(type); 100 | handle.owner = this; 101 | 102 | this._handle = handle; 103 | this._receiving = false; 104 | this._bindState = BIND_STATE_UNBOUND; 105 | this.type = type; 106 | this.fd = null; // compatibility hack 107 | 108 | if (util.isFunction(listener)) 109 | this.on('message', listener); 110 | } 111 | util.inherits(Socket, events.EventEmitter); 112 | exports.Socket = Socket; 113 | 114 | 115 | exports.createSocket = function(type, listener) { 116 | return new Socket(type, listener); 117 | }; 118 | 119 | 120 | function startListening(socket) { 121 | socket._handle.onmessage = onMessage; 122 | // Todo: handle errors 123 | socket._handle.recvStart(); 124 | socket._receiving = true; 125 | socket._bindState = BIND_STATE_BOUND; 126 | socket.fd = -42; // compatibility hack 127 | 128 | socket.emit('listening'); 129 | } 130 | 131 | function replaceHandle(self, newHandle) { 132 | 133 | // Set up the handle that we got from master. 134 | newHandle.lookup = self._handle.lookup; 135 | newHandle.bind = self._handle.bind; 136 | newHandle.send = self._handle.send; 137 | newHandle.owner = self; 138 | 139 | // Replace the existing handle by the handle we got from master. 140 | self._handle.close(); 141 | self._handle = newHandle; 142 | } 143 | 144 | Socket.prototype.bind = function(/*port, address, callback*/) { 145 | var self = this; 146 | 147 | self._healthCheck(); 148 | 149 | if (this._bindState != BIND_STATE_UNBOUND) 150 | throw new Error('Socket is already bound'); 151 | 152 | this._bindState = BIND_STATE_BINDING; 153 | 154 | if (util.isFunction(arguments[arguments.length - 1])) 155 | self.once('listening', arguments[arguments.length - 1]); 156 | 157 | var UDP = process.binding('udp_wrap').UDP; 158 | if (arguments[0] instanceof UDP) { 159 | replaceHandle(self, arguments[0]); 160 | startListening(self); 161 | return; 162 | } 163 | 164 | var port = arguments[0]; 165 | var address = arguments[1]; 166 | if (util.isFunction(address)) address = ''; // a.k.a. "any address" 167 | 168 | // resolve address first 169 | self._handle.lookup(address, function(err, ip) { 170 | if (err) { 171 | self._bindState = BIND_STATE_UNBOUND; 172 | self.emit('error', err); 173 | return; 174 | } 175 | 176 | if (!cluster) 177 | cluster = require('cluster'); 178 | 179 | if (cluster.isWorker) { 180 | cluster._getServer(self, ip, port, self.type, -1, function(err, handle) { 181 | if (err) { 182 | self.emit('error', errnoException(err, 'bind')); 183 | self._bindState = BIND_STATE_UNBOUND; 184 | return; 185 | } 186 | 187 | if (!self._handle) 188 | // handle has been closed in the mean time. 189 | return handle.close(); 190 | 191 | replaceHandle(self, handle); 192 | startListening(self); 193 | }); 194 | 195 | } else { 196 | if (!self._handle) 197 | return; // handle has been closed in the mean time 198 | 199 | var err = self._handle.bind(ip, port || 0, /*flags=*/ 0); 200 | if (err) { 201 | self.emit('error', errnoException(err, 'bind')); 202 | self._bindState = BIND_STATE_UNBOUND; 203 | // Todo: close? 204 | return; 205 | } 206 | 207 | startListening(self); 208 | } 209 | }); 210 | }; 211 | 212 | 213 | // thin wrapper around `send`, here for compatibility with dgram_legacy.js 214 | Socket.prototype.sendto = function(buffer, 215 | offset, 216 | length, 217 | port, 218 | address, 219 | callback) { 220 | if (!util.isNumber(offset) || !util.isNumber(length)) 221 | throw new Error('send takes offset and length as args 2 and 3'); 222 | 223 | if (!util.isString(address)) 224 | throw new Error(this.type + ' sockets must send to port, address'); 225 | 226 | this.send(buffer, offset, length, port, address, callback); 227 | }; 228 | 229 | 230 | Socket.prototype.send = function(buffer, 231 | offset, 232 | length, 233 | port, 234 | address, 235 | callback) { 236 | var self = this; 237 | 238 | if (util.isString(buffer)) 239 | buffer = new Buffer(buffer); 240 | 241 | if (!util.isBuffer(buffer)) 242 | throw new TypeError('First argument must be a buffer or string.'); 243 | 244 | offset = offset | 0; 245 | if (offset < 0) 246 | throw new RangeError('Offset should be >= 0'); 247 | 248 | if (offset >= buffer.length) 249 | throw new RangeError('Offset into buffer too large'); 250 | 251 | // Sending a zero-length datagram is kind of pointless but it _is_ 252 | // allowed, hence check that length >= 0 rather than > 0. 253 | length = length | 0; 254 | if (length < 0) 255 | throw new RangeError('Length should be >= 0'); 256 | 257 | if (offset + length > buffer.length) 258 | throw new RangeError('Offset + length beyond buffer length'); 259 | 260 | port = port | 0; 261 | if (port <= 0 || port > 65535) 262 | throw new RangeError('Port should be > 0 and < 65536'); 263 | 264 | // Normalize callback so it's either a function or undefined but not anything 265 | // else. 266 | if (!util.isFunction(callback)) 267 | callback = undefined; 268 | 269 | self._healthCheck(); 270 | 271 | if (self._bindState == BIND_STATE_UNBOUND) 272 | self.bind(0, null); 273 | 274 | // If the socket hasn't been bound yet, push the outbound packet onto the 275 | // send queue and send after binding is complete. 276 | if (self._bindState != BIND_STATE_BOUND) { 277 | // If the send queue hasn't been initialized yet, do it, and install an 278 | // event handler that flushes the send queue after binding is done. 279 | if (!self._sendQueue) { 280 | self._sendQueue = []; 281 | self.once('listening', function() { 282 | // Flush the send queue. 283 | for (var i = 0; i < self._sendQueue.length; i++) 284 | self.send.apply(self, self._sendQueue[i]); 285 | self._sendQueue = undefined; 286 | }); 287 | } 288 | self._sendQueue.push([buffer, offset, length, port, address, callback]); 289 | return; 290 | } 291 | 292 | self._handle.lookup(address, function(ex, ip) { 293 | if (ex) { 294 | if (callback) callback(ex); 295 | self.emit('error', ex); 296 | } 297 | else if (self._handle) { 298 | var req = { buffer: buffer }; // Keep reference alive. 299 | if (callback) { 300 | req.callback = callback; 301 | req.oncomplete = afterSend; 302 | } 303 | var err = self._handle.send(req, 304 | buffer, 305 | offset, 306 | length, 307 | port, 308 | ip, 309 | !!callback); 310 | if (err && callback) { 311 | // don't emit as error, dgram_legacy.js compatibility 312 | process.nextTick(function() { 313 | callback(errnoException(err, 'send')); 314 | }); 315 | } 316 | } 317 | }); 318 | }; 319 | 320 | 321 | function afterSend(err) { 322 | this.callback(err ? errnoException(err, 'send') : null); 323 | } 324 | 325 | 326 | Socket.prototype.close = function() { 327 | this._healthCheck(); 328 | this._stopReceiving(); 329 | this._handle.close(); 330 | this._handle = null; 331 | this.emit('close'); 332 | }; 333 | 334 | 335 | Socket.prototype.address = function() { 336 | this._healthCheck(); 337 | 338 | var out = {}; 339 | var err = this._handle.getsockname(out); 340 | if (err) { 341 | throw errnoException(err, 'getsockname'); 342 | } 343 | 344 | return out; 345 | }; 346 | 347 | 348 | Socket.prototype.setBroadcast = function(arg) { 349 | var err = this._handle.setBroadcast(arg ? 1 : 0); 350 | if (err) { 351 | throw errnoException(err, 'setBroadcast'); 352 | } 353 | }; 354 | 355 | 356 | Socket.prototype.setTTL = function(arg) { 357 | if (!util.isNumber(arg)) { 358 | throw new TypeError('Argument must be a number'); 359 | } 360 | 361 | var err = this._handle.setTTL(arg); 362 | if (err) { 363 | throw errnoException(err, 'setTTL'); 364 | } 365 | 366 | return arg; 367 | }; 368 | 369 | 370 | Socket.prototype.setMulticastTTL = function(arg) { 371 | if (!util.isNumber(arg)) { 372 | throw new TypeError('Argument must be a number'); 373 | } 374 | 375 | var err = this._handle.setMulticastTTL(arg); 376 | if (err) { 377 | throw errnoException(err, 'setMulticastTTL'); 378 | } 379 | 380 | return arg; 381 | }; 382 | 383 | 384 | Socket.prototype.setMulticastLoopback = function(arg) { 385 | var err = this._handle.setMulticastLoopback(arg ? 1 : 0); 386 | if (err) { 387 | throw errnoException(err, 'setMulticastLoopback'); 388 | } 389 | 390 | return arg; // 0.4 compatibility 391 | }; 392 | 393 | 394 | Socket.prototype.addMembership = function(multicastAddress, 395 | interfaceAddress) { 396 | this._healthCheck(); 397 | 398 | if (!multicastAddress) { 399 | throw new Error('multicast address must be specified'); 400 | } 401 | 402 | var err = this._handle.addMembership(multicastAddress, interfaceAddress); 403 | if (err) { 404 | throw new errnoException(err, 'addMembership'); 405 | } 406 | }; 407 | 408 | 409 | Socket.prototype.dropMembership = function(multicastAddress, 410 | interfaceAddress) { 411 | this._healthCheck(); 412 | 413 | if (!multicastAddress) { 414 | throw new Error('multicast address must be specified'); 415 | } 416 | 417 | var err = this._handle.dropMembership(multicastAddress, interfaceAddress); 418 | if (err) { 419 | throw new errnoException(err, 'dropMembership'); 420 | } 421 | }; 422 | 423 | 424 | Socket.prototype._healthCheck = function() { 425 | if (!this._handle) 426 | throw new Error('Not running'); // error message from dgram_legacy.js 427 | }; 428 | 429 | 430 | Socket.prototype._stopReceiving = function() { 431 | if (!this._receiving) 432 | return; 433 | 434 | this._handle.recvStop(); 435 | this._receiving = false; 436 | this.fd = null; // compatibility hack 437 | }; 438 | 439 | 440 | function onMessage(nread, handle, buf, rinfo) { 441 | var self = handle.owner; 442 | if (nread < 0) { 443 | return self.emit('error', errnoException(nread, 'recvmsg')); 444 | } 445 | rinfo.size = buf.length; // compatibility 446 | self.emit('message', buf, rinfo); 447 | } 448 | 449 | 450 | Socket.prototype.ref = function() { 451 | if (this._handle) 452 | this._handle.ref(); 453 | }; 454 | 455 | 456 | Socket.prototype.unref = function() { 457 | if (this._handle) 458 | this._handle.unref(); 459 | }; 460 | -------------------------------------------------------------------------------- /commonjs/lib/dns.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // 'Software'), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var net = require('net'); 23 | var util = require('util'); 24 | 25 | var cares = process.binding('cares_wrap'); 26 | var uv = process.binding('uv'); 27 | 28 | var isIp = net.isIP; 29 | 30 | 31 | function errnoException(err, syscall, hostname) { 32 | // FIXME(bnoordhuis) Remove this backwards compatibility shite and pass 33 | // the true error to the user. ENOTFOUND is not even a proper POSIX error! 34 | if (err === uv.UV_EAI_MEMORY || 35 | err === uv.UV_EAI_NODATA || 36 | err === uv.UV_EAI_NONAME) { 37 | err = 'ENOTFOUND'; 38 | } 39 | var ex = null; 40 | if (typeof err === 'string') { // c-ares error code. 41 | ex = new Error(syscall + ' ' + err); 42 | ex.code = err; 43 | ex.errno = err; 44 | ex.syscall = syscall; 45 | } else { 46 | ex = util._errnoException(err, syscall); 47 | } 48 | if (hostname) { 49 | ex.hostname = hostname; 50 | } 51 | return ex; 52 | } 53 | 54 | 55 | // c-ares invokes a callback either synchronously or asynchronously, 56 | // but the dns API should always invoke a callback asynchronously. 57 | // 58 | // This function makes sure that the callback is invoked asynchronously. 59 | // It returns a function that invokes the callback within nextTick(). 60 | // 61 | // To avoid invoking unnecessary nextTick(), `immediately` property of 62 | // returned function should be set to true after c-ares returned. 63 | // 64 | // Usage: 65 | // 66 | // function someAPI(callback) { 67 | // callback = makeAsync(callback); 68 | // channel.someAPI(..., callback); 69 | // callback.immediately = true; 70 | // } 71 | function makeAsync(callback) { 72 | if (!util.isFunction(callback)) { 73 | return callback; 74 | } 75 | return function asyncCallback() { 76 | if (asyncCallback.immediately) { 77 | // The API already returned, we can invoke the callback immediately. 78 | callback.apply(null, arguments); 79 | } else { 80 | var args = arguments; 81 | process.nextTick(function() { 82 | callback.apply(null, args); 83 | }); 84 | } 85 | }; 86 | } 87 | 88 | 89 | function onlookup(err, addresses) { 90 | if (err) { 91 | return this.callback(errnoException(err, 'getaddrinfo', this.hostname)); 92 | } 93 | if (this.family) { 94 | this.callback(null, addresses[0], this.family); 95 | } else { 96 | this.callback(null, addresses[0], addresses[0].indexOf(':') >= 0 ? 6 : 4); 97 | } 98 | } 99 | 100 | 101 | // Easy DNS A/AAAA look up 102 | // lookup(hostname, [family,] callback) 103 | exports.lookup = function(hostname, family, callback) { 104 | // parse arguments 105 | if (arguments.length === 2) { 106 | callback = family; 107 | family = 0; 108 | } else if (!family) { 109 | family = 0; 110 | } else { 111 | family = +family; 112 | if (family !== 4 && family !== 6) { 113 | throw new Error('invalid argument: `family` must be 4 or 6'); 114 | } 115 | } 116 | callback = makeAsync(callback); 117 | 118 | if (!hostname) { 119 | callback(null, null, family === 6 ? 6 : 4); 120 | return {}; 121 | } 122 | 123 | var matchedFamily = net.isIP(hostname); 124 | if (matchedFamily) { 125 | callback(null, hostname, matchedFamily); 126 | return {}; 127 | } 128 | 129 | var req = { 130 | callback: callback, 131 | family: family, 132 | hostname: hostname, 133 | oncomplete: onlookup 134 | }; 135 | var err = cares.getaddrinfo(req, hostname, family); 136 | if (err) throw errnoException(err, 'getaddrinfo', hostname); 137 | 138 | callback.immediately = true; 139 | return req; 140 | }; 141 | 142 | 143 | function onresolve(err, result) { 144 | if (err) 145 | this.callback(errnoException(err, this.bindingName, this.hostname)); 146 | else 147 | this.callback(null, result); 148 | } 149 | 150 | 151 | function resolver(bindingName) { 152 | var binding = cares[bindingName]; 153 | 154 | return function query(name, callback) { 155 | callback = makeAsync(callback); 156 | var req = { 157 | bindingName: bindingName, 158 | callback: callback, 159 | hostname: name, 160 | oncomplete: onresolve 161 | }; 162 | var err = binding(req, name); 163 | if (err) throw errnoException(err, bindingName); 164 | callback.immediately = true; 165 | return req; 166 | } 167 | } 168 | 169 | 170 | var resolveMap = {}; 171 | exports.resolve4 = resolveMap.A = resolver('queryA'); 172 | exports.resolve6 = resolveMap.AAAA = resolver('queryAaaa'); 173 | exports.resolveCname = resolveMap.CNAME = resolver('queryCname'); 174 | exports.resolveMx = resolveMap.MX = resolver('queryMx'); 175 | exports.resolveNs = resolveMap.NS = resolver('queryNs'); 176 | exports.resolveTxt = resolveMap.TXT = resolver('queryTxt'); 177 | exports.resolveSrv = resolveMap.SRV = resolver('querySrv'); 178 | exports.resolveNaptr = resolveMap.NAPTR = resolver('queryNaptr'); 179 | exports.reverse = resolveMap.PTR = resolver('getHostByAddr'); 180 | 181 | 182 | exports.resolve = function(hostname, type_, callback_) { 183 | var resolver, callback; 184 | if (util.isString(type_)) { 185 | resolver = resolveMap[type_]; 186 | callback = callback_; 187 | } else { 188 | resolver = exports.resolve4; 189 | callback = type_; 190 | } 191 | 192 | if (util.isFunction(resolver)) { 193 | return resolver(hostname, callback); 194 | } else { 195 | throw new Error('Unknown type "' + type_ + '"'); 196 | } 197 | }; 198 | 199 | 200 | exports.getServers = function() { 201 | return cares.getServers(); 202 | }; 203 | 204 | 205 | exports.setServers = function(servers) { 206 | // cache the original servers because in the event of an error setting the 207 | // servers cares won't have any servers available for resolution 208 | var orig = cares.getServers(); 209 | 210 | var newSet = []; 211 | 212 | servers.forEach(function(serv) { 213 | var ver = isIp(serv); 214 | 215 | if (ver) 216 | return newSet.push([ver, serv]); 217 | 218 | var match = serv.match(/\[(.*)\](:\d+)?/); 219 | 220 | // we have an IPv6 in brackets 221 | if (match) { 222 | ver = isIp(match[1]); 223 | if (ver) 224 | return newSet.push([ver, match[1]]); 225 | } 226 | 227 | var s = serv.split(/:\d+$/)[0]; 228 | ver = isIp(s); 229 | 230 | if (ver) 231 | return newSet.push([ver, s]); 232 | 233 | throw new Error('IP address is not properly formatted: ' + serv); 234 | }); 235 | 236 | var r = cares.setServers(newSet); 237 | 238 | if (r) { 239 | // reset the servers to the old servers, because ares probably unset them 240 | cares.setServers(orig.join(',')); 241 | 242 | var err = cares.strerror(r); 243 | throw new Error('c-ares failed to set servers: "' + err + 244 | '" [' + servers + ']'); 245 | } 246 | }; 247 | 248 | 249 | // ERROR CODES 250 | exports.NODATA = 'ENODATA'; 251 | exports.FORMERR = 'EFORMERR'; 252 | exports.SERVFAIL = 'ESERVFAIL'; 253 | exports.NOTFOUND = 'ENOTFOUND'; 254 | exports.NOTIMP = 'ENOTIMP'; 255 | exports.REFUSED = 'EREFUSED'; 256 | exports.BADQUERY = 'EBADQUERY'; 257 | exports.ADNAME = 'EADNAME'; 258 | exports.BADFAMILY = 'EBADFAMILY'; 259 | exports.BADRESP = 'EBADRESP'; 260 | exports.CONNREFUSED = 'ECONNREFUSED'; 261 | exports.TIMEOUT = 'ETIMEOUT'; 262 | exports.EOF = 'EOF'; 263 | exports.FILE = 'EFILE'; 264 | exports.NOMEM = 'ENOMEM'; 265 | exports.DESTRUCTION = 'EDESTRUCTION'; 266 | exports.BADSTR = 'EBADSTR'; 267 | exports.BADFLAGS = 'EBADFLAGS'; 268 | exports.NONAME = 'ENONAME'; 269 | exports.BADHINTS = 'EBADHINTS'; 270 | exports.NOTINITIALIZED = 'ENOTINITIALIZED'; 271 | exports.LOADIPHLPAPI = 'ELOADIPHLPAPI'; 272 | exports.ADDRGETNETWORKPARAMS = 'EADDRGETNETWORKPARAMS'; 273 | exports.CANCELLED = 'ECANCELLED'; 274 | -------------------------------------------------------------------------------- /commonjs/lib/domain.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var util = require('util'); 23 | var EventEmitter = require('events'); 24 | var inherits = util.inherits; 25 | 26 | // communicate with events module, but don't require that 27 | // module to have to load this one, since this module has 28 | // a few side effects. 29 | EventEmitter.usingDomains = true; 30 | 31 | exports.Domain = Domain; 32 | 33 | exports.create = exports.createDomain = function() { 34 | return new Domain(); 35 | }; 36 | 37 | // it's possible to enter one domain while already inside 38 | // another one. the stack is each entered domain. 39 | var stack = []; 40 | exports._stack = stack; 41 | // the active domain is always the one that we're currently in. 42 | exports.active = null; 43 | 44 | 45 | function noop() { } 46 | 47 | 48 | var listenerObj = { 49 | error: function errorHandler(domain, er) { 50 | var caught = false; 51 | // ignore errors on disposed domains. 52 | // 53 | // XXX This is a bit stupid. We should probably get rid of 54 | // domain.dispose() altogether. It's almost always a terrible 55 | // idea. --isaacs 56 | if (domain._disposed) 57 | return true; 58 | 59 | er.domain = domain; 60 | er.domainThrown = true; 61 | // wrap this in a try/catch so we don't get infinite throwing 62 | try { 63 | // One of three things will happen here. 64 | // 65 | // 1. There is a handler, caught = true 66 | // 2. There is no handler, caught = false 67 | // 3. It throws, caught = false 68 | // 69 | // If caught is false after this, then there's no need to exit() 70 | // the domain, because we're going to crash the process anyway. 71 | caught = domain.emit('error', er); 72 | 73 | if (stack.length === 0) 74 | process.removeAsyncListener(domain._listener); 75 | 76 | // Exit all domains on the stack. Uncaught exceptions end the 77 | // current tick and no domains should be left on the stack 78 | // between ticks. 79 | stack.length = 0; 80 | exports.active = process.domain = null; 81 | } catch (er2) { 82 | // The domain error handler threw! oh no! 83 | // See if another domain can catch THIS error, 84 | // or else crash on the original one. 85 | // If the user already exited it, then don't double-exit. 86 | if (domain === exports.active) { 87 | stack.pop(); 88 | } 89 | if (stack.length) { 90 | exports.active = process.domain = stack[stack.length - 1]; 91 | caught = process._fatalException(er2); 92 | } else { 93 | caught = false; 94 | } 95 | return caught; 96 | } 97 | return caught; 98 | } 99 | }; 100 | 101 | 102 | inherits(Domain, EventEmitter); 103 | 104 | function Domain() { 105 | EventEmitter.call(this); 106 | this.members = []; 107 | this._listener = process.createAsyncListener(noop, listenerObj, this); 108 | } 109 | 110 | Domain.prototype.members = undefined; 111 | Domain.prototype._disposed = undefined; 112 | Domain.prototype._listener = undefined; 113 | 114 | 115 | Domain.prototype.enter = function() { 116 | if (this._disposed) return; 117 | 118 | // note that this might be a no-op, but we still need 119 | // to push it onto the stack so that we can pop it later. 120 | exports.active = process.domain = this; 121 | stack.push(this); 122 | 123 | process.addAsyncListener(this._listener); 124 | }; 125 | 126 | 127 | Domain.prototype.exit = function() { 128 | if (this._disposed) return; 129 | 130 | process.removeAsyncListener(this._listener); 131 | 132 | // exit all domains until this one. 133 | var index = stack.lastIndexOf(this); 134 | if (index !== -1) 135 | stack.splice(index + 1); 136 | else 137 | stack.length = 0; 138 | 139 | exports.active = stack[stack.length - 1]; 140 | process.domain = exports.active; 141 | }; 142 | 143 | 144 | // note: this works for timers as well. 145 | Domain.prototype.add = function(ee) { 146 | // If the domain is disposed or already added, then nothing left to do. 147 | if (this._disposed || ee.domain === this) 148 | return; 149 | 150 | // has a domain already - remove it first. 151 | if (ee.domain) 152 | ee.domain.remove(ee); 153 | 154 | // check for circular Domain->Domain links. 155 | // This causes bad insanity! 156 | // 157 | // For example: 158 | // var d = domain.create(); 159 | // var e = domain.create(); 160 | // d.add(e); 161 | // e.add(d); 162 | // e.emit('error', er); // RangeError, stack overflow! 163 | if (this.domain && (ee instanceof Domain)) { 164 | for (var d = this.domain; d; d = d.domain) { 165 | if (ee === d) return; 166 | } 167 | } 168 | 169 | ee.domain = this; 170 | this.members.push(ee); 171 | 172 | // Adding the domain._listener to the Wrap associated with the event 173 | // emitter instance will be done automatically either on class 174 | // instantiation or manually, like in cases of net listen(). 175 | // The reason it cannot be done here is because in specific cases the 176 | // _handle is not created on EE instantiation, so there's no place to 177 | // add the listener. 178 | }; 179 | 180 | 181 | Domain.prototype.remove = function(ee) { 182 | ee.domain = null; 183 | var index = this.members.indexOf(ee); 184 | if (index !== -1) 185 | this.members.splice(index, 1); 186 | 187 | // First check if the ee is a handle itself. 188 | if (ee.removeAsyncListener) 189 | ee.removeAsyncListener(this._listener); 190 | 191 | // Manually remove the asyncListener from the handle, if possible. 192 | if (ee._handle && ee._handle.removeAsyncListener) 193 | ee._handle.removeAsyncListener(this._listener); 194 | 195 | // TODO(trevnorris): Are there cases where the handle doesn't live on 196 | // the ee or the _handle. 197 | 198 | // TODO(trevnorris): For debugging that we've missed adding AsyncWrap's 199 | // methods to a handle somewhere on the native side. 200 | if (ee._handle && !ee._handle.removeAsyncListener) { 201 | process._rawDebug('Wrap handle is missing AsyncWrap methods'); 202 | process.abort(); 203 | } 204 | }; 205 | 206 | 207 | Domain.prototype.run = function(fn) { 208 | if (this._disposed) 209 | return; 210 | this.enter(); 211 | var ret = fn.call(this); 212 | this.exit(); 213 | return ret; 214 | }; 215 | 216 | 217 | function intercepted(_this, self, cb, fnargs) { 218 | if (self._disposed) 219 | return; 220 | 221 | if (fnargs[0] && fnargs[0] instanceof Error) { 222 | var er = fnargs[0]; 223 | util._extend(er, { 224 | domainBound: cb, 225 | domainThrown: false, 226 | domain: self 227 | }); 228 | self.emit('error', er); 229 | return; 230 | } 231 | 232 | var len = fnargs.length; 233 | var args = []; 234 | var i, ret; 235 | 236 | self.enter(); 237 | if (fnargs.length > 1) { 238 | for (i = 1; i < fnargs.length; i++) 239 | args.push(fnargs[i]); 240 | ret = cb.apply(_this, args); 241 | } else { 242 | ret = cb.call(_this); 243 | } 244 | self.exit(); 245 | 246 | return ret; 247 | } 248 | 249 | 250 | Domain.prototype.intercept = function(cb) { 251 | var self = this; 252 | 253 | function runIntercepted() { 254 | return intercepted(this, self, cb, arguments); 255 | } 256 | 257 | return runIntercepted; 258 | }; 259 | 260 | 261 | function bound(_this, self, cb, fnargs) { 262 | if (self._disposed) 263 | return; 264 | 265 | var len = fnargs.length; 266 | var args = []; 267 | var i, ret; 268 | 269 | self.enter(); 270 | if (fnargs.length > 0) 271 | ret = cb.apply(_this, fnargs); 272 | else 273 | ret = cb.call(_this); 274 | self.exit(); 275 | 276 | return ret; 277 | } 278 | 279 | 280 | Domain.prototype.bind = function(cb) { 281 | var self = this; 282 | 283 | function runBound() { 284 | return bound(this, self, cb, arguments); 285 | } 286 | 287 | runBound.domain = this; 288 | 289 | return runBound; 290 | }; 291 | 292 | 293 | Domain.prototype.dispose = util.deprecate(function() { 294 | if (this._disposed) return; 295 | 296 | // if we're the active domain, then get out now. 297 | this.exit(); 298 | 299 | // remove from parent domain, if there is one. 300 | if (this.domain) this.domain.remove(this); 301 | 302 | // kill the references so that they can be properly gc'ed. 303 | this.members.length = 0; 304 | 305 | // mark this domain as 'no longer relevant' 306 | // so that it can't be entered or activated. 307 | this._disposed = true; 308 | }); 309 | -------------------------------------------------------------------------------- /commonjs/lib/events.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var domain; 23 | var util = require('util'); 24 | 25 | function EventEmitter() { 26 | EventEmitter.init.call(this); 27 | } 28 | module.exports = EventEmitter; 29 | 30 | // Backwards-compat with node 0.10.x 31 | EventEmitter.EventEmitter = EventEmitter; 32 | 33 | EventEmitter.usingDomains = false; 34 | 35 | EventEmitter.prototype.domain = undefined; 36 | EventEmitter.prototype._events = undefined; 37 | EventEmitter.prototype._maxListeners = undefined; 38 | 39 | // By default EventEmitters will print a warning if more than 10 listeners are 40 | // added to it. This is a useful default which helps finding memory leaks. 41 | EventEmitter.defaultMaxListeners = 10; 42 | 43 | EventEmitter.init = function() { 44 | this.domain = null; 45 | if (EventEmitter.usingDomains) { 46 | // if there is an active domain, then attach to it. 47 | domain = domain || require('domain'); 48 | if (domain.active && !(this instanceof domain.Domain)) { 49 | this.domain = domain.active; 50 | } 51 | } 52 | this._events = this._events || {}; 53 | this._maxListeners = this._maxListeners || undefined; 54 | }; 55 | 56 | // Obviously not all Emitters should be limited to 10. This function allows 57 | // that to be increased. Set to zero for unlimited. 58 | EventEmitter.prototype.setMaxListeners = function(n) { 59 | if (!util.isNumber(n) || n < 0 || isNaN(n)) 60 | throw TypeError('n must be a positive number'); 61 | this._maxListeners = n; 62 | return this; 63 | }; 64 | 65 | EventEmitter.prototype.emit = function(type) { 66 | var er, handler, len, args, i, listeners; 67 | 68 | if (!this._events) 69 | this._events = {}; 70 | 71 | // If there is no 'error' event listener then throw. 72 | if (type === 'error' && !this._events.error) { 73 | er = arguments[1]; 74 | if (this.domain) { 75 | if (!er) 76 | er = new Error('Uncaught, unspecified "error" event.'); 77 | er.domainEmitter = this; 78 | er.domain = this.domain; 79 | er.domainThrown = false; 80 | this.domain.emit('error', er); 81 | } else if (er instanceof Error) { 82 | throw er; // Unhandled 'error' event 83 | } else { 84 | throw Error('Uncaught, unspecified "error" event.'); 85 | } 86 | return false; 87 | } 88 | 89 | handler = this._events[type]; 90 | 91 | if (util.isUndefined(handler)) 92 | return false; 93 | 94 | if (util.isFunction(handler)) { 95 | switch (arguments.length) { 96 | // fast cases 97 | case 1: 98 | handler.call(this); 99 | break; 100 | case 2: 101 | handler.call(this, arguments[1]); 102 | break; 103 | case 3: 104 | handler.call(this, arguments[1], arguments[2]); 105 | break; 106 | // slower 107 | default: 108 | len = arguments.length; 109 | args = new Array(len - 1); 110 | for (i = 1; i < len; i++) 111 | args[i - 1] = arguments[i]; 112 | handler.apply(this, args); 113 | } 114 | } else if (util.isObject(handler)) { 115 | len = arguments.length; 116 | args = new Array(len - 1); 117 | for (i = 1; i < len; i++) 118 | args[i - 1] = arguments[i]; 119 | 120 | listeners = handler.slice(); 121 | len = listeners.length; 122 | for (i = 0; i < len; i++) 123 | listeners[i].apply(this, args); 124 | } 125 | 126 | return true; 127 | }; 128 | 129 | EventEmitter.prototype.addListener = function(type, listener) { 130 | var m; 131 | 132 | if (!util.isFunction(listener)) 133 | throw TypeError('listener must be a function'); 134 | 135 | if (!this._events) 136 | this._events = {}; 137 | 138 | // To avoid recursion in the case that type === "newListener"! Before 139 | // adding it to the listeners, first emit "newListener". 140 | if (this._events.newListener) 141 | this.emit('newListener', type, 142 | util.isFunction(listener.listener) ? 143 | listener.listener : listener); 144 | 145 | if (!this._events[type]) 146 | // Optimize the case of one listener. Don't need the extra array object. 147 | this._events[type] = listener; 148 | else if (util.isObject(this._events[type])) 149 | // If we've already got an array, just append. 150 | this._events[type].push(listener); 151 | else 152 | // Adding the second element, need to change to array. 153 | this._events[type] = [this._events[type], listener]; 154 | 155 | // Check for listener leak 156 | if (util.isObject(this._events[type]) && !this._events[type].warned) { 157 | var m; 158 | if (!util.isUndefined(this._maxListeners)) { 159 | m = this._maxListeners; 160 | } else { 161 | m = EventEmitter.defaultMaxListeners; 162 | } 163 | 164 | if (m && m > 0 && this._events[type].length > m) { 165 | this._events[type].warned = true; 166 | console.error('(node) warning: possible EventEmitter memory ' + 167 | 'leak detected. %d listeners added. ' + 168 | 'Use emitter.setMaxListeners() to increase limit.', 169 | this._events[type].length); 170 | console.trace(); 171 | } 172 | } 173 | 174 | return this; 175 | }; 176 | 177 | EventEmitter.prototype.on = EventEmitter.prototype.addListener; 178 | 179 | EventEmitter.prototype.once = function(type, listener) { 180 | if (!util.isFunction(listener)) 181 | throw TypeError('listener must be a function'); 182 | 183 | var fired = false; 184 | 185 | function g() { 186 | this.removeListener(type, g); 187 | 188 | if (!fired) { 189 | fired = true; 190 | listener.apply(this, arguments); 191 | } 192 | } 193 | 194 | g.listener = listener; 195 | this.on(type, g); 196 | 197 | return this; 198 | }; 199 | 200 | // emits a 'removeListener' event iff the listener was removed 201 | EventEmitter.prototype.removeListener = function(type, listener) { 202 | var list, position, length, i; 203 | 204 | if (!util.isFunction(listener)) 205 | throw TypeError('listener must be a function'); 206 | 207 | if (!this._events || !this._events[type]) 208 | return this; 209 | 210 | list = this._events[type]; 211 | length = list.length; 212 | position = -1; 213 | 214 | if (list === listener || 215 | (util.isFunction(list.listener) && list.listener === listener)) { 216 | delete this._events[type]; 217 | if (this._events.removeListener) 218 | this.emit('removeListener', type, listener); 219 | 220 | } else if (util.isObject(list)) { 221 | for (i = length; i-- > 0;) { 222 | if (list[i] === listener || 223 | (list[i].listener && list[i].listener === listener)) { 224 | position = i; 225 | break; 226 | } 227 | } 228 | 229 | if (position < 0) 230 | return this; 231 | 232 | if (list.length === 1) { 233 | list.length = 0; 234 | delete this._events[type]; 235 | } else { 236 | list.splice(position, 1); 237 | } 238 | 239 | if (this._events.removeListener) 240 | this.emit('removeListener', type, listener); 241 | } 242 | 243 | return this; 244 | }; 245 | 246 | EventEmitter.prototype.removeAllListeners = function(type) { 247 | var key, listeners; 248 | 249 | if (!this._events) 250 | return this; 251 | 252 | // not listening for removeListener, no need to emit 253 | if (!this._events.removeListener) { 254 | if (arguments.length === 0) 255 | this._events = {}; 256 | else if (this._events[type]) 257 | delete this._events[type]; 258 | return this; 259 | } 260 | 261 | // emit removeListener for all listeners on all events 262 | if (arguments.length === 0) { 263 | for (key in this._events) { 264 | if (key === 'removeListener') continue; 265 | this.removeAllListeners(key); 266 | } 267 | this.removeAllListeners('removeListener'); 268 | this._events = {}; 269 | return this; 270 | } 271 | 272 | listeners = this._events[type]; 273 | 274 | if (util.isFunction(listeners)) { 275 | this.removeListener(type, listeners); 276 | } else if (Array.isArray(listeners)) { 277 | // LIFO order 278 | while (listeners.length) 279 | this.removeListener(type, listeners[listeners.length - 1]); 280 | } 281 | delete this._events[type]; 282 | 283 | return this; 284 | }; 285 | 286 | EventEmitter.prototype.listeners = function(type) { 287 | var ret; 288 | if (!this._events || !this._events[type]) 289 | ret = []; 290 | else if (util.isFunction(this._events[type])) 291 | ret = [this._events[type]]; 292 | else 293 | ret = this._events[type].slice(); 294 | return ret; 295 | }; 296 | 297 | EventEmitter.listenerCount = function(emitter, type) { 298 | var ret; 299 | if (!emitter._events || !emitter._events[type]) 300 | ret = 0; 301 | else if (util.isFunction(emitter._events[type])) 302 | ret = 1; 303 | else 304 | ret = emitter._events[type].length; 305 | return ret; 306 | }; 307 | -------------------------------------------------------------------------------- /commonjs/lib/freelist.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // This is a free list to avoid creating so many of the same object. 23 | exports.FreeList = function(name, max, constructor) { 24 | this.name = name; 25 | this.constructor = constructor; 26 | this.max = max; 27 | this.list = []; 28 | }; 29 | 30 | 31 | exports.FreeList.prototype.alloc = function() { 32 | //debug("alloc " + this.name + " " + this.list.length); 33 | return this.list.length ? this.list.shift() : 34 | this.constructor.apply(this, arguments); 35 | }; 36 | 37 | 38 | exports.FreeList.prototype.free = function(obj) { 39 | //debug("free " + this.name + " " + this.list.length); 40 | if (this.list.length < this.max) { 41 | this.list.push(obj); 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /commonjs/lib/http.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var util = require('util'); 23 | var EventEmitter = require('events').EventEmitter; 24 | 25 | 26 | var incoming = require('_http_incoming'); 27 | var IncomingMessage = exports.IncomingMessage = incoming.IncomingMessage; 28 | 29 | 30 | var common = require('_http_common'); 31 | exports.METHODS = util._extend([], common.methods).sort(); 32 | exports.parsers = common.parsers; 33 | 34 | 35 | var outgoing = require('_http_outgoing'); 36 | var OutgoingMessage = exports.OutgoingMessage = outgoing.OutgoingMessage; 37 | 38 | 39 | var server = require('_http_server'); 40 | exports.ServerResponse = server.ServerResponse; 41 | exports.STATUS_CODES = server.STATUS_CODES; 42 | 43 | 44 | var agent = require('_http_agent'); 45 | var Agent = exports.Agent = agent.Agent; 46 | var globalAgent = exports.globalAgent = agent.globalAgent; 47 | 48 | var client = require('_http_client'); 49 | var ClientRequest = exports.ClientRequest = client.ClientRequest; 50 | 51 | exports.request = function(options, cb) { 52 | return globalAgent.request(options, cb); 53 | }; 54 | 55 | exports.get = function(options, cb) { 56 | return globalAgent.get(options, cb); 57 | }; 58 | 59 | exports._connectionListener = server._connectionListener; 60 | var Server = exports.Server = server.Server; 61 | 62 | exports.createServer = function(requestListener) { 63 | return new Server(requestListener); 64 | }; 65 | 66 | 67 | // Legacy Interface 68 | 69 | function Client(port, host) { 70 | if (!(this instanceof Client)) return new Client(port, host); 71 | EventEmitter.call(this); 72 | 73 | host = host || 'localhost'; 74 | port = port || 80; 75 | this.host = host; 76 | this.port = port; 77 | this.agent = new Agent({ host: host, port: port, maxSockets: 1 }); 78 | } 79 | util.inherits(Client, EventEmitter); 80 | Client.prototype.request = function(method, path, headers) { 81 | var self = this; 82 | var options = {}; 83 | options.host = self.host; 84 | options.port = self.port; 85 | if (method[0] === '/') { 86 | headers = path; 87 | path = method; 88 | method = 'GET'; 89 | } 90 | options.method = method; 91 | options.path = path; 92 | options.headers = headers; 93 | options.agent = self.agent; 94 | var c = new ClientRequest(options); 95 | c.on('error', function(e) { 96 | self.emit('error', e); 97 | }); 98 | // The old Client interface emitted 'end' on socket end. 99 | // This doesn't map to how we want things to operate in the future 100 | // but it will get removed when we remove this legacy interface. 101 | c.on('socket', function(s) { 102 | s.on('end', function() { 103 | if (self._decoder) { 104 | var ret = self._decoder.end(); 105 | if (ret) 106 | self.emit('data', ret); 107 | } 108 | self.emit('end'); 109 | }); 110 | }); 111 | return c; 112 | }; 113 | 114 | exports.Client = util.deprecate(Client, 115 | 'http.Client will be removed soon. Do not use it.'); 116 | 117 | exports.createClient = util.deprecate(function(port, host) { 118 | return new Client(port, host); 119 | }, 'http.createClient is deprecated. Use `http.request` instead.'); 120 | -------------------------------------------------------------------------------- /commonjs/lib/https.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var tls = require('tls'); 23 | var http = require('http'); 24 | var util = require('util'); 25 | var inherits = require('util').inherits; 26 | var debug = util.debuglog('https'); 27 | 28 | function Server(opts, requestListener) { 29 | if (!(this instanceof Server)) return new Server(opts, requestListener); 30 | 31 | if (process.features.tls_npn && !opts.NPNProtocols) { 32 | opts.NPNProtocols = ['http/1.1', 'http/1.0']; 33 | } 34 | 35 | tls.Server.call(this, opts, http._connectionListener); 36 | 37 | this.httpAllowHalfOpen = false; 38 | 39 | if (requestListener) { 40 | this.addListener('request', requestListener); 41 | } 42 | 43 | this.addListener('clientError', function(err, conn) { 44 | conn.destroy(); 45 | }); 46 | 47 | this.timeout = 2 * 60 * 1000; 48 | } 49 | inherits(Server, tls.Server); 50 | exports.Server = Server; 51 | 52 | Server.prototype.setTimeout = http.Server.prototype.setTimeout; 53 | 54 | exports.createServer = function(opts, requestListener) { 55 | return new Server(opts, requestListener); 56 | }; 57 | 58 | 59 | // HTTPS agents. 60 | 61 | function createConnection(port, host, options) { 62 | if (util.isObject(port)) { 63 | options = port; 64 | } else if (util.isObject(host)) { 65 | options = host; 66 | } else if (util.isObject(options)) { 67 | options = options; 68 | } else { 69 | options = {}; 70 | } 71 | 72 | if (util.isNumber(port)) { 73 | options.port = port; 74 | } 75 | 76 | if (util.isString(host)) { 77 | options.host = host; 78 | } 79 | 80 | debug('createConnection', options); 81 | return tls.connect(options); 82 | } 83 | 84 | 85 | function Agent(options) { 86 | http.Agent.call(this, options); 87 | this.defaultPort = 443; 88 | this.protocol = 'https:'; 89 | } 90 | inherits(Agent, http.Agent); 91 | Agent.prototype.createConnection = createConnection; 92 | 93 | Agent.prototype.getName = function(options) { 94 | var name = http.Agent.prototype.getName.call(this, options); 95 | 96 | name += ':'; 97 | if (options.ca) 98 | name += options.ca; 99 | 100 | name += ':'; 101 | if (options.cert) 102 | name += options.cert; 103 | 104 | name += ':'; 105 | if (options.ciphers) 106 | name += options.ciphers; 107 | 108 | name += ':'; 109 | if (options.key) 110 | name += options.key; 111 | 112 | name += ':'; 113 | if (options.pfx) 114 | name += options.pfx; 115 | 116 | name += ':'; 117 | if (!util.isUndefined(options.rejectUnauthorized)) 118 | name += options.rejectUnauthorized; 119 | 120 | return name; 121 | }; 122 | 123 | var globalAgent = new Agent(); 124 | 125 | exports.globalAgent = globalAgent; 126 | exports.Agent = Agent; 127 | 128 | exports.request = function(options, cb) { 129 | return globalAgent.request(options, cb); 130 | }; 131 | 132 | exports.get = function(options, cb) { 133 | return globalAgent.get(options, cb); 134 | }; 135 | -------------------------------------------------------------------------------- /commonjs/lib/os.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var binding = process.binding('os'); 23 | var util = require('util'); 24 | var isWindows = process.platform === 'win32'; 25 | 26 | exports.endianness = binding.getEndianness; 27 | exports.hostname = binding.getHostname; 28 | exports.loadavg = binding.getLoadAvg; 29 | exports.uptime = binding.getUptime; 30 | exports.freemem = binding.getFreeMem; 31 | exports.totalmem = binding.getTotalMem; 32 | exports.cpus = binding.getCPUs; 33 | exports.type = binding.getOSType; 34 | exports.release = binding.getOSRelease; 35 | exports.networkInterfaces = binding.getInterfaceAddresses; 36 | 37 | exports.arch = function() { 38 | return process.arch; 39 | }; 40 | 41 | exports.platform = function() { 42 | return process.platform; 43 | }; 44 | 45 | exports.tmpdir = function() { 46 | if (isWindows) { 47 | return process.env.TEMP || 48 | process.env.TMP || 49 | (process.env.SystemRoot || process.env.windir) + '\\temp'; 50 | } else { 51 | return process.env.TMPDIR || 52 | process.env.TMP || 53 | process.env.TEMP || 54 | '/tmp'; 55 | } 56 | }; 57 | 58 | exports.tmpDir = exports.tmpdir; 59 | 60 | exports.getNetworkInterfaces = util.deprecate(function() { 61 | return exports.networkInterfaces(); 62 | }, 'getNetworkInterfaces is now called `os.networkInterfaces`.'); 63 | 64 | exports.EOL = isWindows ? '\r\n' : '\n'; 65 | -------------------------------------------------------------------------------- /commonjs/lib/punycode.js: -------------------------------------------------------------------------------- 1 | /*! http://mths.be/punycode v1.2.3 by @mathias */ 2 | ;(function(root) { 3 | 4 | /** Detect free variables */ 5 | var freeExports = typeof exports == 'object' && exports; 6 | var freeModule = typeof module == 'object' && module && 7 | module.exports == freeExports && module; 8 | var freeGlobal = typeof global == 'object' && global; 9 | if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { 10 | root = freeGlobal; 11 | } 12 | 13 | /** 14 | * The `punycode` object. 15 | * @name punycode 16 | * @type Object 17 | */ 18 | var punycode, 19 | 20 | /** Highest positive signed 32-bit float value */ 21 | maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 22 | 23 | /** Bootstring parameters */ 24 | base = 36, 25 | tMin = 1, 26 | tMax = 26, 27 | skew = 38, 28 | damp = 700, 29 | initialBias = 72, 30 | initialN = 128, // 0x80 31 | delimiter = '-', // '\x2D' 32 | 33 | /** Regular expressions */ 34 | regexPunycode = /^xn--/, 35 | regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars 36 | regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators 37 | 38 | /** Error messages */ 39 | errors = { 40 | 'overflow': 'Overflow: input needs wider integers to process', 41 | 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', 42 | 'invalid-input': 'Invalid input' 43 | }, 44 | 45 | /** Convenience shortcuts */ 46 | baseMinusTMin = base - tMin, 47 | floor = Math.floor, 48 | stringFromCharCode = String.fromCharCode, 49 | 50 | /** Temporary variable */ 51 | key; 52 | 53 | /*--------------------------------------------------------------------------*/ 54 | 55 | /** 56 | * A generic error utility function. 57 | * @private 58 | * @param {String} type The error type. 59 | * @returns {Error} Throws a `RangeError` with the applicable error message. 60 | */ 61 | function error(type) { 62 | throw RangeError(errors[type]); 63 | } 64 | 65 | /** 66 | * A generic `Array#map` utility function. 67 | * @private 68 | * @param {Array} array The array to iterate over. 69 | * @param {Function} callback The function that gets called for every array 70 | * item. 71 | * @returns {Array} A new array of values returned by the callback function. 72 | */ 73 | function map(array, fn) { 74 | var length = array.length; 75 | while (length--) { 76 | array[length] = fn(array[length]); 77 | } 78 | return array; 79 | } 80 | 81 | /** 82 | * A simple `Array#map`-like wrapper to work with domain name strings. 83 | * @private 84 | * @param {String} domain The domain name. 85 | * @param {Function} callback The function that gets called for every 86 | * character. 87 | * @returns {Array} A new string of characters returned by the callback 88 | * function. 89 | */ 90 | function mapDomain(string, fn) { 91 | return map(string.split(regexSeparators), fn).join('.'); 92 | } 93 | 94 | /** 95 | * Creates an array containing the numeric code points of each Unicode 96 | * character in the string. While JavaScript uses UCS-2 internally, 97 | * this function will convert a pair of surrogate halves (each of which 98 | * UCS-2 exposes as separate characters) into a single code point, 99 | * matching UTF-16. 100 | * @see `punycode.ucs2.encode` 101 | * @see 102 | * @memberOf punycode.ucs2 103 | * @name decode 104 | * @param {String} string The Unicode input string (UCS-2). 105 | * @returns {Array} The new array of code points. 106 | */ 107 | function ucs2decode(string) { 108 | var output = [], 109 | counter = 0, 110 | length = string.length, 111 | value, 112 | extra; 113 | while (counter < length) { 114 | value = string.charCodeAt(counter++); 115 | if (value >= 0xD800 && value <= 0xDBFF && counter < length) { 116 | // high surrogate, and there is a next character 117 | extra = string.charCodeAt(counter++); 118 | if ((extra & 0xFC00) == 0xDC00) { // low surrogate 119 | output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); 120 | } else { 121 | // unmatched surrogate; only append this code unit, in case the next 122 | // code unit is the high surrogate of a surrogate pair 123 | output.push(value); 124 | counter--; 125 | } 126 | } else { 127 | output.push(value); 128 | } 129 | } 130 | return output; 131 | } 132 | 133 | /** 134 | * Creates a string based on an array of numeric code points. 135 | * @see `punycode.ucs2.decode` 136 | * @memberOf punycode.ucs2 137 | * @name encode 138 | * @param {Array} codePoints The array of numeric code points. 139 | * @returns {String} The new Unicode string (UCS-2). 140 | */ 141 | function ucs2encode(array) { 142 | return map(array, function(value) { 143 | var output = ''; 144 | if (value > 0xFFFF) { 145 | value -= 0x10000; 146 | output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); 147 | value = 0xDC00 | value & 0x3FF; 148 | } 149 | output += stringFromCharCode(value); 150 | return output; 151 | }).join(''); 152 | } 153 | 154 | /** 155 | * Converts a basic code point into a digit/integer. 156 | * @see `digitToBasic()` 157 | * @private 158 | * @param {Number} codePoint The basic numeric code point value. 159 | * @returns {Number} The numeric value of a basic code point (for use in 160 | * representing integers) in the range `0` to `base - 1`, or `base` if 161 | * the code point does not represent a value. 162 | */ 163 | function basicToDigit(codePoint) { 164 | if (codePoint - 48 < 10) { 165 | return codePoint - 22; 166 | } 167 | if (codePoint - 65 < 26) { 168 | return codePoint - 65; 169 | } 170 | if (codePoint - 97 < 26) { 171 | return codePoint - 97; 172 | } 173 | return base; 174 | } 175 | 176 | /** 177 | * Converts a digit/integer into a basic code point. 178 | * @see `basicToDigit()` 179 | * @private 180 | * @param {Number} digit The numeric value of a basic code point. 181 | * @returns {Number} The basic code point whose value (when used for 182 | * representing integers) is `digit`, which needs to be in the range 183 | * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is 184 | * used; else, the lowercase form is used. The behavior is undefined 185 | * if `flag` is non-zero and `digit` has no uppercase form. 186 | */ 187 | function digitToBasic(digit, flag) { 188 | // 0..25 map to ASCII a..z or A..Z 189 | // 26..35 map to ASCII 0..9 190 | return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); 191 | } 192 | 193 | /** 194 | * Bias adaptation function as per section 3.4 of RFC 3492. 195 | * http://tools.ietf.org/html/rfc3492#section-3.4 196 | * @private 197 | */ 198 | function adapt(delta, numPoints, firstTime) { 199 | var k = 0; 200 | delta = firstTime ? floor(delta / damp) : delta >> 1; 201 | delta += floor(delta / numPoints); 202 | for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { 203 | delta = floor(delta / baseMinusTMin); 204 | } 205 | return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); 206 | } 207 | 208 | /** 209 | * Converts a Punycode string of ASCII-only symbols to a string of Unicode 210 | * symbols. 211 | * @memberOf punycode 212 | * @param {String} input The Punycode string of ASCII-only symbols. 213 | * @returns {String} The resulting string of Unicode symbols. 214 | */ 215 | function decode(input) { 216 | // Don't use UCS-2 217 | var output = [], 218 | inputLength = input.length, 219 | out, 220 | i = 0, 221 | n = initialN, 222 | bias = initialBias, 223 | basic, 224 | j, 225 | index, 226 | oldi, 227 | w, 228 | k, 229 | digit, 230 | t, 231 | /** Cached calculation results */ 232 | baseMinusT; 233 | 234 | // Handle the basic code points: let `basic` be the number of input code 235 | // points before the last delimiter, or `0` if there is none, then copy 236 | // the first basic code points to the output. 237 | 238 | basic = input.lastIndexOf(delimiter); 239 | if (basic < 0) { 240 | basic = 0; 241 | } 242 | 243 | for (j = 0; j < basic; ++j) { 244 | // if it's not a basic code point 245 | if (input.charCodeAt(j) >= 0x80) { 246 | error('not-basic'); 247 | } 248 | output.push(input.charCodeAt(j)); 249 | } 250 | 251 | // Main decoding loop: start just after the last delimiter if any basic code 252 | // points were copied; start at the beginning otherwise. 253 | 254 | for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { 255 | 256 | // `index` is the index of the next character to be consumed. 257 | // Decode a generalized variable-length integer into `delta`, 258 | // which gets added to `i`. The overflow checking is easier 259 | // if we increase `i` as we go, then subtract off its starting 260 | // value at the end to obtain `delta`. 261 | for (oldi = i, w = 1, k = base; /* no condition */; k += base) { 262 | 263 | if (index >= inputLength) { 264 | error('invalid-input'); 265 | } 266 | 267 | digit = basicToDigit(input.charCodeAt(index++)); 268 | 269 | if (digit >= base || digit > floor((maxInt - i) / w)) { 270 | error('overflow'); 271 | } 272 | 273 | i += digit * w; 274 | t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); 275 | 276 | if (digit < t) { 277 | break; 278 | } 279 | 280 | baseMinusT = base - t; 281 | if (w > floor(maxInt / baseMinusT)) { 282 | error('overflow'); 283 | } 284 | 285 | w *= baseMinusT; 286 | 287 | } 288 | 289 | out = output.length + 1; 290 | bias = adapt(i - oldi, out, oldi == 0); 291 | 292 | // `i` was supposed to wrap around from `out` to `0`, 293 | // incrementing `n` each time, so we'll fix that now: 294 | if (floor(i / out) > maxInt - n) { 295 | error('overflow'); 296 | } 297 | 298 | n += floor(i / out); 299 | i %= out; 300 | 301 | // Insert `n` at position `i` of the output 302 | output.splice(i++, 0, n); 303 | 304 | } 305 | 306 | return ucs2encode(output); 307 | } 308 | 309 | /** 310 | * Converts a string of Unicode symbols to a Punycode string of ASCII-only 311 | * symbols. 312 | * @memberOf punycode 313 | * @param {String} input The string of Unicode symbols. 314 | * @returns {String} The resulting Punycode string of ASCII-only symbols. 315 | */ 316 | function encode(input) { 317 | var n, 318 | delta, 319 | handledCPCount, 320 | basicLength, 321 | bias, 322 | j, 323 | m, 324 | q, 325 | k, 326 | t, 327 | currentValue, 328 | output = [], 329 | /** `inputLength` will hold the number of code points in `input`. */ 330 | inputLength, 331 | /** Cached calculation results */ 332 | handledCPCountPlusOne, 333 | baseMinusT, 334 | qMinusT; 335 | 336 | // Convert the input in UCS-2 to Unicode 337 | input = ucs2decode(input); 338 | 339 | // Cache the length 340 | inputLength = input.length; 341 | 342 | // Initialize the state 343 | n = initialN; 344 | delta = 0; 345 | bias = initialBias; 346 | 347 | // Handle the basic code points 348 | for (j = 0; j < inputLength; ++j) { 349 | currentValue = input[j]; 350 | if (currentValue < 0x80) { 351 | output.push(stringFromCharCode(currentValue)); 352 | } 353 | } 354 | 355 | handledCPCount = basicLength = output.length; 356 | 357 | // `handledCPCount` is the number of code points that have been handled; 358 | // `basicLength` is the number of basic code points. 359 | 360 | // Finish the basic string - if it is not empty - with a delimiter 361 | if (basicLength) { 362 | output.push(delimiter); 363 | } 364 | 365 | // Main encoding loop: 366 | while (handledCPCount < inputLength) { 367 | 368 | // All non-basic code points < n have been handled already. Find the next 369 | // larger one: 370 | for (m = maxInt, j = 0; j < inputLength; ++j) { 371 | currentValue = input[j]; 372 | if (currentValue >= n && currentValue < m) { 373 | m = currentValue; 374 | } 375 | } 376 | 377 | // Increase `delta` enough to advance the decoder's state to , 378 | // but guard against overflow 379 | handledCPCountPlusOne = handledCPCount + 1; 380 | if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { 381 | error('overflow'); 382 | } 383 | 384 | delta += (m - n) * handledCPCountPlusOne; 385 | n = m; 386 | 387 | for (j = 0; j < inputLength; ++j) { 388 | currentValue = input[j]; 389 | 390 | if (currentValue < n && ++delta > maxInt) { 391 | error('overflow'); 392 | } 393 | 394 | if (currentValue == n) { 395 | // Represent delta as a generalized variable-length integer 396 | for (q = delta, k = base; /* no condition */; k += base) { 397 | t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); 398 | if (q < t) { 399 | break; 400 | } 401 | qMinusT = q - t; 402 | baseMinusT = base - t; 403 | output.push( 404 | stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) 405 | ); 406 | q = floor(qMinusT / baseMinusT); 407 | } 408 | 409 | output.push(stringFromCharCode(digitToBasic(q, 0))); 410 | bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); 411 | delta = 0; 412 | ++handledCPCount; 413 | } 414 | } 415 | 416 | ++delta; 417 | ++n; 418 | 419 | } 420 | return output.join(''); 421 | } 422 | 423 | /** 424 | * Converts a Punycode string representing a domain name to Unicode. Only the 425 | * Punycoded parts of the domain name will be converted, i.e. it doesn't 426 | * matter if you call it on a string that has already been converted to 427 | * Unicode. 428 | * @memberOf punycode 429 | * @param {String} domain The Punycode domain name to convert to Unicode. 430 | * @returns {String} The Unicode representation of the given Punycode 431 | * string. 432 | */ 433 | function toUnicode(domain) { 434 | return mapDomain(domain, function(string) { 435 | return regexPunycode.test(string) 436 | ? decode(string.slice(4).toLowerCase()) 437 | : string; 438 | }); 439 | } 440 | 441 | /** 442 | * Converts a Unicode string representing a domain name to Punycode. Only the 443 | * non-ASCII parts of the domain name will be converted, i.e. it doesn't 444 | * matter if you call it with a domain that's already in ASCII. 445 | * @memberOf punycode 446 | * @param {String} domain The domain name to convert, as a Unicode string. 447 | * @returns {String} The Punycode representation of the given domain name. 448 | */ 449 | function toASCII(domain) { 450 | return mapDomain(domain, function(string) { 451 | return regexNonASCII.test(string) 452 | ? 'xn--' + encode(string) 453 | : string; 454 | }); 455 | } 456 | 457 | /*--------------------------------------------------------------------------*/ 458 | 459 | /** Define the public API */ 460 | punycode = { 461 | /** 462 | * A string representing the current Punycode.js version number. 463 | * @memberOf punycode 464 | * @type String 465 | */ 466 | 'version': '1.2.3', 467 | /** 468 | * An object of methods to convert from JavaScript's internal character 469 | * representation (UCS-2) to Unicode code points, and back. 470 | * @see 471 | * @memberOf punycode 472 | * @type Object 473 | */ 474 | 'ucs2': { 475 | 'decode': ucs2decode, 476 | 'encode': ucs2encode 477 | }, 478 | 'decode': decode, 479 | 'encode': encode, 480 | 'toASCII': toASCII, 481 | 'toUnicode': toUnicode 482 | }; 483 | 484 | /** Expose `punycode` */ 485 | // Some AMD build optimizers, like r.js, check for specific condition patterns 486 | // like the following: 487 | if ( 488 | typeof define == 'function' && 489 | typeof define.amd == 'object' && 490 | define.amd 491 | ) { 492 | define(function() { 493 | return punycode; 494 | }); 495 | } else if (freeExports && !freeExports.nodeType) { 496 | if (freeModule) { // in Node.js or RingoJS v0.8.0+ 497 | freeModule.exports = punycode; 498 | } else { // in Narwhal or RingoJS v0.7.0- 499 | for (key in punycode) { 500 | punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); 501 | } 502 | } 503 | } else { // in Rhino or a web browser 504 | root.punycode = punycode; 505 | } 506 | 507 | }(this)); 508 | -------------------------------------------------------------------------------- /commonjs/lib/querystring.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // Query String Utilities 23 | 24 | var QueryString = exports; 25 | var util = require('util'); 26 | 27 | 28 | // If obj.hasOwnProperty has been overridden, then calling 29 | // obj.hasOwnProperty(prop) will break. 30 | // See: https://github.com/joyent/node/issues/1707 31 | function hasOwnProperty(obj, prop) { 32 | return Object.prototype.hasOwnProperty.call(obj, prop); 33 | } 34 | 35 | 36 | function charCode(c) { 37 | return c.charCodeAt(0); 38 | } 39 | 40 | 41 | // a safe fast alternative to decodeURIComponent 42 | QueryString.unescapeBuffer = function(s, decodeSpaces) { 43 | var out = new Buffer(s.length); 44 | var state = 'CHAR'; // states: CHAR, HEX0, HEX1 45 | var n, m, hexchar; 46 | 47 | for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) { 48 | var c = s.charCodeAt(inIndex); 49 | switch (state) { 50 | case 'CHAR': 51 | switch (c) { 52 | case charCode('%'): 53 | n = 0; 54 | m = 0; 55 | state = 'HEX0'; 56 | break; 57 | case charCode('+'): 58 | if (decodeSpaces) c = charCode(' '); 59 | // pass thru 60 | default: 61 | out[outIndex++] = c; 62 | break; 63 | } 64 | break; 65 | 66 | case 'HEX0': 67 | state = 'HEX1'; 68 | hexchar = c; 69 | if (charCode('0') <= c && c <= charCode('9')) { 70 | n = c - charCode('0'); 71 | } else if (charCode('a') <= c && c <= charCode('f')) { 72 | n = c - charCode('a') + 10; 73 | } else if (charCode('A') <= c && c <= charCode('F')) { 74 | n = c - charCode('A') + 10; 75 | } else { 76 | out[outIndex++] = charCode('%'); 77 | out[outIndex++] = c; 78 | state = 'CHAR'; 79 | break; 80 | } 81 | break; 82 | 83 | case 'HEX1': 84 | state = 'CHAR'; 85 | if (charCode('0') <= c && c <= charCode('9')) { 86 | m = c - charCode('0'); 87 | } else if (charCode('a') <= c && c <= charCode('f')) { 88 | m = c - charCode('a') + 10; 89 | } else if (charCode('A') <= c && c <= charCode('F')) { 90 | m = c - charCode('A') + 10; 91 | } else { 92 | out[outIndex++] = charCode('%'); 93 | out[outIndex++] = hexchar; 94 | out[outIndex++] = c; 95 | break; 96 | } 97 | out[outIndex++] = 16 * n + m; 98 | break; 99 | } 100 | } 101 | 102 | // TODO support returning arbitrary buffers. 103 | 104 | return out.slice(0, outIndex - 1); 105 | }; 106 | 107 | 108 | QueryString.unescape = function(s, decodeSpaces) { 109 | return QueryString.unescapeBuffer(s, decodeSpaces).toString(); 110 | }; 111 | 112 | 113 | QueryString.escape = function(str) { 114 | return encodeURIComponent(str); 115 | }; 116 | 117 | var stringifyPrimitive = function(v) { 118 | if (util.isString(v)) 119 | return v; 120 | if (util.isBoolean(v)) 121 | return v ? 'true' : 'false'; 122 | if (util.isNumber(v)) 123 | return isFinite(v) ? v : ''; 124 | return ''; 125 | }; 126 | 127 | 128 | QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) { 129 | sep = sep || '&'; 130 | eq = eq || '='; 131 | if (util.isNull(obj)) { 132 | obj = undefined; 133 | } 134 | 135 | if (util.isObject(obj)) { 136 | return Object.keys(obj).map(function(k) { 137 | var ks = QueryString.escape(stringifyPrimitive(k)) + eq; 138 | if (util.isArray(obj[k])) { 139 | return obj[k].map(function(v) { 140 | return ks + QueryString.escape(stringifyPrimitive(v)); 141 | }).join(sep); 142 | } else { 143 | return ks + QueryString.escape(stringifyPrimitive(obj[k])); 144 | } 145 | }).join(sep); 146 | 147 | } 148 | 149 | if (!name) return ''; 150 | return QueryString.escape(stringifyPrimitive(name)) + eq + 151 | QueryString.escape(stringifyPrimitive(obj)); 152 | }; 153 | 154 | // Parse a key=val string. 155 | QueryString.parse = QueryString.decode = function(qs, sep, eq, options) { 156 | sep = sep || '&'; 157 | eq = eq || '='; 158 | var obj = {}; 159 | 160 | if (!util.isString(qs) || qs.length === 0) { 161 | return obj; 162 | } 163 | 164 | var regexp = /\+/g; 165 | qs = qs.split(sep); 166 | 167 | var maxKeys = 1000; 168 | if (options && util.isNumber(options.maxKeys)) { 169 | maxKeys = options.maxKeys; 170 | } 171 | 172 | var len = qs.length; 173 | // maxKeys <= 0 means that we should not limit keys count 174 | if (maxKeys > 0 && len > maxKeys) { 175 | len = maxKeys; 176 | } 177 | 178 | for (var i = 0; i < len; ++i) { 179 | var x = qs[i].replace(regexp, '%20'), 180 | idx = x.indexOf(eq), 181 | kstr, vstr, k, v; 182 | 183 | if (idx >= 0) { 184 | kstr = x.substr(0, idx); 185 | vstr = x.substr(idx + 1); 186 | } else { 187 | kstr = x; 188 | vstr = ''; 189 | } 190 | 191 | try { 192 | k = decodeURIComponent(kstr); 193 | v = decodeURIComponent(vstr); 194 | } catch (e) { 195 | k = QueryString.unescape(kstr, true); 196 | v = QueryString.unescape(vstr, true); 197 | } 198 | 199 | if (!hasOwnProperty(obj, k)) { 200 | obj[k] = v; 201 | } else if (util.isArray(obj[k])) { 202 | obj[k].push(v); 203 | } else { 204 | obj[k] = [obj[k], v]; 205 | } 206 | } 207 | 208 | return obj; 209 | }; 210 | -------------------------------------------------------------------------------- /commonjs/lib/smalloc.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var smalloc = process.binding('smalloc'); 23 | var kMaxLength = smalloc.kMaxLength; 24 | var util = require('util'); 25 | 26 | exports.alloc = alloc; 27 | exports.copyOnto = smalloc.copyOnto; 28 | exports.dispose = dispose; 29 | exports.hasExternalData = smalloc.hasExternalData; 30 | 31 | // don't allow kMaxLength to accidentally be overwritten. it's a lot less 32 | // apparent when a primitive is accidentally changed. 33 | Object.defineProperty(exports, 'kMaxLength', { 34 | enumerable: true, value: kMaxLength, writable: false 35 | }); 36 | 37 | // enumerated values for different external array types 38 | var Types = {}; 39 | 40 | Object.defineProperties(Types, { 41 | 'Int8': { enumerable: true, value: 1, writable: false }, 42 | 'Uint8': { enumerable: true, value: 2, writable: false }, 43 | 'Int16': { enumerable: true, value: 3, writable: false }, 44 | 'Uint16': { enumerable: true, value: 4, writable: false }, 45 | 'Int32': { enumerable: true, value: 5, writable: false }, 46 | 'Uint32': { enumerable: true, value: 6, writable: false }, 47 | 'Float': { enumerable: true, value: 7, writable: false }, 48 | 'Double': { enumerable: true, value: 8, writable: false }, 49 | 'Uint8Clamped': { enumerable: true, value: 9, writable: false } 50 | }); 51 | 52 | Object.defineProperty(exports, 'Types', { 53 | enumerable: true, value: Types, writable: false 54 | }); 55 | 56 | 57 | // usage: obj = alloc(n[, obj][, type]); 58 | function alloc(n, obj, type) { 59 | n = n >>> 0; 60 | 61 | if (util.isUndefined(obj)) 62 | obj = {}; 63 | 64 | if (util.isNumber(obj)) { 65 | type = obj >>> 0; 66 | obj = {}; 67 | } else if (util.isPrimitive(obj)) { 68 | throw new TypeError('obj must be an Object'); 69 | } 70 | 71 | // 1 == v8::kExternalByteArray, 9 == v8::kExternalPixelArray 72 | if (type < 1 || type > 9) 73 | throw new TypeError('unknown external array type: ' + type); 74 | if (util.isArray(obj)) 75 | throw new TypeError('Arrays are not supported'); 76 | if (n > kMaxLength) 77 | throw new RangeError('n > kMaxLength'); 78 | 79 | return smalloc.alloc(obj, n, type); 80 | } 81 | 82 | 83 | function dispose(obj) { 84 | if (util.isPrimitive(obj)) 85 | throw new TypeError('obj must be an Object'); 86 | if (util.isBuffer(obj)) 87 | throw new TypeError('obj cannot be a Buffer'); 88 | 89 | smalloc.dispose(obj); 90 | } 91 | -------------------------------------------------------------------------------- /commonjs/lib/stream.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | module.exports = Stream; 23 | 24 | var EE = require('events').EventEmitter; 25 | var util = require('util'); 26 | 27 | util.inherits(Stream, EE); 28 | Stream.Readable = require('_stream_readable'); 29 | Stream.Writable = require('_stream_writable'); 30 | Stream.Duplex = require('_stream_duplex'); 31 | Stream.Transform = require('_stream_transform'); 32 | Stream.PassThrough = require('_stream_passthrough'); 33 | 34 | // Backwards-compat with node 0.4.x 35 | Stream.Stream = Stream; 36 | 37 | 38 | 39 | // old-style streams. Note that the pipe method (the only relevant 40 | // part of this class) is overridden in the Readable class. 41 | 42 | function Stream() { 43 | EE.call(this); 44 | } 45 | 46 | Stream.prototype.pipe = function(dest, options) { 47 | var source = this; 48 | 49 | function ondata(chunk) { 50 | if (dest.writable) { 51 | if (false === dest.write(chunk) && source.pause) { 52 | source.pause(); 53 | } 54 | } 55 | } 56 | 57 | source.on('data', ondata); 58 | 59 | function ondrain() { 60 | if (source.readable && source.resume) { 61 | source.resume(); 62 | } 63 | } 64 | 65 | dest.on('drain', ondrain); 66 | 67 | // If the 'end' option is not supplied, dest.end() will be called when 68 | // source gets the 'end' or 'close' events. Only dest.end() once. 69 | if (!dest._isStdio && (!options || options.end !== false)) { 70 | source.on('end', onend); 71 | source.on('close', onclose); 72 | } 73 | 74 | var didOnEnd = false; 75 | function onend() { 76 | if (didOnEnd) return; 77 | didOnEnd = true; 78 | 79 | dest.end(); 80 | } 81 | 82 | 83 | function onclose() { 84 | if (didOnEnd) return; 85 | didOnEnd = true; 86 | 87 | if (util.isFunction(dest.destroy)) dest.destroy(); 88 | } 89 | 90 | // don't leave dangling pipes when there are errors. 91 | function onerror(er) { 92 | cleanup(); 93 | if (EE.listenerCount(this, 'error') === 0) { 94 | throw er; // Unhandled stream error in pipe. 95 | } 96 | } 97 | 98 | source.on('error', onerror); 99 | dest.on('error', onerror); 100 | 101 | // remove all the event listeners that were added. 102 | function cleanup() { 103 | source.removeListener('data', ondata); 104 | dest.removeListener('drain', ondrain); 105 | 106 | source.removeListener('end', onend); 107 | source.removeListener('close', onclose); 108 | 109 | source.removeListener('error', onerror); 110 | dest.removeListener('error', onerror); 111 | 112 | source.removeListener('end', cleanup); 113 | source.removeListener('close', cleanup); 114 | 115 | dest.removeListener('close', cleanup); 116 | } 117 | 118 | source.on('end', cleanup); 119 | source.on('close', cleanup); 120 | 121 | dest.on('close', cleanup); 122 | 123 | dest.emit('pipe', source); 124 | 125 | // Allow for unix-like usage: A.pipe(B).pipe(C) 126 | return dest; 127 | }; 128 | -------------------------------------------------------------------------------- /commonjs/lib/string_decoder.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | function assertEncoding(encoding) { 23 | if (encoding && !Buffer.isEncoding(encoding)) { 24 | throw new Error('Unknown encoding: ' + encoding); 25 | } 26 | } 27 | 28 | var StringDecoder = exports.StringDecoder = function(encoding) { 29 | this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); 30 | assertEncoding(encoding); 31 | switch (this.encoding) { 32 | case 'utf8': 33 | // CESU-8 represents each of Surrogate Pair by 3-bytes 34 | this.surrogateSize = 3; 35 | break; 36 | case 'ucs2': 37 | case 'utf16le': 38 | // UTF-16 represents each of Surrogate Pair by 2-bytes 39 | this.surrogateSize = 2; 40 | this.detectIncompleteChar = utf16DetectIncompleteChar; 41 | break; 42 | case 'base64': 43 | // Base-64 stores 3 bytes in 4 chars, and pads the remainder. 44 | this.surrogateSize = 3; 45 | this.detectIncompleteChar = base64DetectIncompleteChar; 46 | break; 47 | default: 48 | this.write = passThroughWrite; 49 | return; 50 | } 51 | 52 | this.charBuffer = new Buffer(6); 53 | this.charReceived = 0; 54 | this.charLength = 0; 55 | }; 56 | 57 | 58 | StringDecoder.prototype.write = function(buffer) { 59 | var charStr = ''; 60 | var offset = 0; 61 | 62 | // if our last write ended with an incomplete multibyte character 63 | while (this.charLength) { 64 | // determine how many remaining bytes this buffer has to offer for this char 65 | var i = (buffer.length >= this.charLength - this.charReceived) ? 66 | this.charLength - this.charReceived : 67 | buffer.length; 68 | 69 | // add the new bytes to the char buffer 70 | buffer.copy(this.charBuffer, this.charReceived, offset, i); 71 | this.charReceived += (i - offset); 72 | offset = i; 73 | 74 | if (this.charReceived < this.charLength) { 75 | // still not enough chars in this buffer? wait for more ... 76 | return ''; 77 | } 78 | 79 | // get the character that was split 80 | charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); 81 | 82 | // lead surrogate (D800-DBFF) is also the incomplete character 83 | var charCode = charStr.charCodeAt(charStr.length - 1); 84 | if (charCode >= 0xD800 && charCode <= 0xDBFF) { 85 | this.charLength += this.surrogateSize; 86 | charStr = ''; 87 | continue; 88 | } 89 | this.charReceived = this.charLength = 0; 90 | 91 | // if there are no more bytes in this buffer, just emit our char 92 | if (i == buffer.length) return charStr; 93 | 94 | // otherwise cut off the characters end from the beginning of this buffer 95 | buffer = buffer.slice(i, buffer.length); 96 | break; 97 | } 98 | 99 | var lenIncomplete = this.detectIncompleteChar(buffer); 100 | 101 | var end = buffer.length; 102 | if (this.charLength) { 103 | // buffer the incomplete character bytes we got 104 | buffer.copy(this.charBuffer, 0, buffer.length - lenIncomplete, end); 105 | this.charReceived = lenIncomplete; 106 | end -= lenIncomplete; 107 | } 108 | 109 | charStr += buffer.toString(this.encoding, 0, end); 110 | 111 | var end = charStr.length - 1; 112 | var charCode = charStr.charCodeAt(end); 113 | // lead surrogate (D800-DBFF) is also the incomplete character 114 | if (charCode >= 0xD800 && charCode <= 0xDBFF) { 115 | var size = this.surrogateSize; 116 | this.charLength += size; 117 | this.charReceived += size; 118 | this.charBuffer.copy(this.charBuffer, size, 0, size); 119 | this.charBuffer.write(charStr.charAt(charStr.length - 1), this.encoding); 120 | return charStr.substring(0, end); 121 | } 122 | 123 | // or just emit the charStr 124 | return charStr; 125 | }; 126 | 127 | StringDecoder.prototype.detectIncompleteChar = function(buffer) { 128 | // determine how many bytes we have to check at the end of this buffer 129 | var i = (buffer.length >= 3) ? 3 : buffer.length; 130 | 131 | // Figure out if one of the last i bytes of our buffer announces an 132 | // incomplete char. 133 | for (; i > 0; i--) { 134 | var c = buffer[buffer.length - i]; 135 | 136 | // See http://en.wikipedia.org/wiki/UTF-8#Description 137 | 138 | // 110XXXXX 139 | if (i == 1 && c >> 5 == 0x06) { 140 | this.charLength = 2; 141 | break; 142 | } 143 | 144 | // 1110XXXX 145 | if (i <= 2 && c >> 4 == 0x0E) { 146 | this.charLength = 3; 147 | break; 148 | } 149 | 150 | // 11110XXX 151 | if (i <= 3 && c >> 3 == 0x1E) { 152 | this.charLength = 4; 153 | break; 154 | } 155 | } 156 | 157 | return i; 158 | }; 159 | 160 | StringDecoder.prototype.end = function(buffer) { 161 | var res = ''; 162 | if (buffer && buffer.length) 163 | res = this.write(buffer); 164 | 165 | if (this.charReceived) { 166 | var cr = this.charReceived; 167 | var buf = this.charBuffer; 168 | var enc = this.encoding; 169 | res += buf.slice(0, cr).toString(enc); 170 | } 171 | 172 | return res; 173 | }; 174 | 175 | function passThroughWrite(buffer) { 176 | return buffer.toString(this.encoding); 177 | } 178 | 179 | function utf16DetectIncompleteChar(buffer) { 180 | var incomplete = this.charReceived = buffer.length % 2; 181 | this.charLength = incomplete ? 2 : 0; 182 | return incomplete; 183 | } 184 | 185 | function base64DetectIncompleteChar(buffer) { 186 | var incomplete = this.charReceived = buffer.length % 3; 187 | this.charLength = incomplete ? 3 : 0; 188 | return incomplete; 189 | } 190 | -------------------------------------------------------------------------------- /commonjs/lib/sys.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // the sys module was renamed to 'util'. 23 | // this shim remains to keep old programs working. 24 | module.exports = require('util'); 25 | -------------------------------------------------------------------------------- /commonjs/lib/tls.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var net = require('net'); 23 | var url = require('url'); 24 | var util = require('util'); 25 | 26 | exports.DEFAULT_CIPHERS = 27 | 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:' + // TLS 1.2 28 | 'RC4:HIGH:!MD5:!aNULL:!EDH'; // TLS 1.0 29 | 30 | exports.DEFAULT_ECDH_CURVE = 'prime256v1'; 31 | 32 | // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations 33 | // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more 34 | // renegotations are seen. The settings are applied to all remote client 35 | // connections. 36 | exports.CLIENT_RENEG_LIMIT = 3; 37 | exports.CLIENT_RENEG_WINDOW = 600; 38 | 39 | exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024; 40 | 41 | exports.getCiphers = function() { 42 | var names = process.binding('crypto').getSSLCiphers(); 43 | // Drop all-caps names in favor of their lowercase aliases, 44 | var ctx = {}; 45 | names.forEach(function(name) { 46 | if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); 47 | ctx[name] = true; 48 | }); 49 | return Object.getOwnPropertyNames(ctx).sort(); 50 | }; 51 | 52 | // Convert protocols array into valid OpenSSL protocols list 53 | // ("\x06spdy/2\x08http/1.1\x08http/1.0") 54 | exports.convertNPNProtocols = function convertNPNProtocols(NPNProtocols, out) { 55 | // If NPNProtocols is Array - translate it into buffer 56 | if (util.isArray(NPNProtocols)) { 57 | var buff = new Buffer(NPNProtocols.reduce(function(p, c) { 58 | return p + 1 + Buffer.byteLength(c); 59 | }, 0)); 60 | 61 | NPNProtocols.reduce(function(offset, c) { 62 | var clen = Buffer.byteLength(c); 63 | buff[offset] = clen; 64 | buff.write(c, offset + 1); 65 | 66 | return offset + 1 + clen; 67 | }, 0); 68 | 69 | NPNProtocols = buff; 70 | } 71 | 72 | // If it's already a Buffer - store it 73 | if (util.isBuffer(NPNProtocols)) { 74 | out.NPNProtocols = NPNProtocols; 75 | } 76 | }; 77 | 78 | exports.checkServerIdentity = function checkServerIdentity(host, cert) { 79 | // Create regexp to much hostnames 80 | function regexpify(host, wildcards) { 81 | // Add trailing dot (make hostnames uniform) 82 | if (!/\.$/.test(host)) host += '.'; 83 | 84 | // The same applies to hostname with more than one wildcard, 85 | // if hostname has wildcard when wildcards are not allowed, 86 | // or if there are less than two dots after wildcard (i.e. *.com or *d.com) 87 | // 88 | // also 89 | // 90 | // "The client SHOULD NOT attempt to match a presented identifier in 91 | // which the wildcard character comprises a label other than the 92 | // left-most label (e.g., do not match bar.*.example.net)." 93 | // RFC6125 94 | if (!wildcards && /\*/.test(host) || /[\.\*].*\*/.test(host) || 95 | /\*/.test(host) && !/\*.*\..+\..+/.test(host)) { 96 | return /$./; 97 | } 98 | 99 | // Replace wildcard chars with regexp's wildcard and 100 | // escape all characters that have special meaning in regexps 101 | // (i.e. '.', '[', '{', '*', and others) 102 | var re = host.replace( 103 | /\*([a-z0-9\\-_\.])|[\.,\-\\\^\$+?*\[\]\(\):!\|{}]/g, 104 | function(all, sub) { 105 | if (sub) return '[a-z0-9\\-_]*' + (sub === '-' ? '\\-' : sub); 106 | return '\\' + all; 107 | }); 108 | 109 | return new RegExp('^' + re + '$', 'i'); 110 | } 111 | 112 | var dnsNames = [], 113 | uriNames = [], 114 | ips = [], 115 | matchCN = true, 116 | valid = false; 117 | 118 | // There're several names to perform check against: 119 | // CN and altnames in certificate extension 120 | // (DNS names, IP addresses, and URIs) 121 | // 122 | // Walk through altnames and generate lists of those names 123 | if (cert.subjectaltname) { 124 | cert.subjectaltname.split(/, /g).forEach(function(altname) { 125 | if (/^DNS:/.test(altname)) { 126 | dnsNames.push(altname.slice(4)); 127 | } else if (/^IP Address:/.test(altname)) { 128 | ips.push(altname.slice(11)); 129 | } else if (/^URI:/.test(altname)) { 130 | var uri = url.parse(altname.slice(4)); 131 | if (uri) uriNames.push(uri.hostname); 132 | } 133 | }); 134 | } 135 | 136 | // If hostname is an IP address, it should be present in the list of IP 137 | // addresses. 138 | if (net.isIP(host)) { 139 | valid = ips.some(function(ip) { 140 | return ip === host; 141 | }); 142 | } else { 143 | // Transform hostname to canonical form 144 | if (!/\.$/.test(host)) host += '.'; 145 | 146 | // Otherwise check all DNS/URI records from certificate 147 | // (with allowed wildcards) 148 | dnsNames = dnsNames.map(function(name) { 149 | return regexpify(name, true); 150 | }); 151 | 152 | // Wildcards ain't allowed in URI names 153 | uriNames = uriNames.map(function(name) { 154 | return regexpify(name, false); 155 | }); 156 | 157 | dnsNames = dnsNames.concat(uriNames); 158 | 159 | if (dnsNames.length > 0) matchCN = false; 160 | 161 | // Match against Common Name (CN) only if no supported identifiers are 162 | // present. 163 | // 164 | // "As noted, a client MUST NOT seek a match for a reference identifier 165 | // of CN-ID if the presented identifiers include a DNS-ID, SRV-ID, 166 | // URI-ID, or any application-specific identifier types supported by the 167 | // client." 168 | // RFC6125 169 | if (matchCN) { 170 | var commonNames = cert.subject.CN; 171 | if (util.isArray(commonNames)) { 172 | for (var i = 0, k = commonNames.length; i < k; ++i) { 173 | dnsNames.push(regexpify(commonNames[i], true)); 174 | } 175 | } else { 176 | dnsNames.push(regexpify(commonNames, true)); 177 | } 178 | } 179 | 180 | valid = dnsNames.some(function(re) { 181 | return re.test(host); 182 | }); 183 | } 184 | 185 | return valid; 186 | }; 187 | 188 | // Example: 189 | // C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org 190 | exports.parseCertString = function parseCertString(s) { 191 | var out = {}; 192 | var parts = s.split('\n'); 193 | for (var i = 0, len = parts.length; i < len; i++) { 194 | var sepIndex = parts[i].indexOf('='); 195 | if (sepIndex > 0) { 196 | var key = parts[i].slice(0, sepIndex); 197 | var value = parts[i].slice(sepIndex + 1); 198 | if (key in out) { 199 | if (!util.isArray(out[key])) { 200 | out[key] = [out[key]]; 201 | } 202 | out[key].push(value); 203 | } else { 204 | out[key] = value; 205 | } 206 | } 207 | } 208 | return out; 209 | }; 210 | 211 | // Public API 212 | exports.TLSSocket = require('_tls_wrap').TLSSocket; 213 | exports.Server = require('_tls_wrap').Server; 214 | exports.createServer = require('_tls_wrap').createServer; 215 | exports.connect = require('_tls_wrap').connect; 216 | 217 | // Legacy API 218 | exports.__defineGetter__('createSecurePair', util.deprecate(function() { 219 | return require('_tls_legacy').createSecurePair; 220 | }, 'createSecurePair() is deprecated, use TLSSocket instead')); 221 | -------------------------------------------------------------------------------- /commonjs/lib/tty.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var inherits = require('util').inherits; 23 | var net = require('net'); 24 | var TTY = process.binding('tty_wrap').TTY; 25 | var isTTY = process.binding('tty_wrap').isTTY; 26 | var util = require('util'); 27 | 28 | var errnoException = util._errnoException; 29 | 30 | 31 | exports.isatty = function(fd) { 32 | return isTTY(fd); 33 | }; 34 | 35 | 36 | // backwards-compat 37 | exports.setRawMode = util.deprecate(function(flag) { 38 | if (!process.stdin.isTTY) { 39 | throw new Error('can\'t set raw mode on non-tty'); 40 | } 41 | process.stdin.setRawMode(flag); 42 | }, 'tty.setRawMode: Use `process.stdin.setRawMode()` instead.'); 43 | 44 | 45 | function ReadStream(fd, options) { 46 | if (!(this instanceof ReadStream)) 47 | return new ReadStream(fd, options); 48 | 49 | options = util._extend({ 50 | highWaterMark: 0, 51 | readable: true, 52 | writable: false, 53 | handle: new TTY(fd, true) 54 | }, options); 55 | 56 | net.Socket.call(this, options); 57 | 58 | this.isRaw = false; 59 | this.isTTY = true; 60 | } 61 | inherits(ReadStream, net.Socket); 62 | 63 | exports.ReadStream = ReadStream; 64 | 65 | ReadStream.prototype.setRawMode = function(flag) { 66 | flag = !!flag; 67 | this._handle.setRawMode(flag); 68 | this.isRaw = flag; 69 | }; 70 | 71 | 72 | 73 | function WriteStream(fd) { 74 | if (!(this instanceof WriteStream)) return new WriteStream(fd); 75 | net.Socket.call(this, { 76 | handle: new TTY(fd, false), 77 | readable: false, 78 | writable: true 79 | }); 80 | 81 | var winSize = []; 82 | var err = this._handle.getWindowSize(winSize); 83 | if (!err) { 84 | this.columns = winSize[0]; 85 | this.rows = winSize[1]; 86 | } 87 | } 88 | inherits(WriteStream, net.Socket); 89 | exports.WriteStream = WriteStream; 90 | 91 | 92 | WriteStream.prototype.isTTY = true; 93 | 94 | 95 | WriteStream.prototype._refreshSize = function() { 96 | var oldCols = this.columns; 97 | var oldRows = this.rows; 98 | var winSize = []; 99 | var err = this._handle.getWindowSize(winSize); 100 | if (err) { 101 | this.emit('error', errnoException(err, 'getWindowSize')); 102 | return; 103 | } 104 | var newCols = winSize[0]; 105 | var newRows = winSize[1]; 106 | if (oldCols !== newCols || oldRows !== newRows) { 107 | this.columns = newCols; 108 | this.rows = newRows; 109 | this.emit('resize'); 110 | } 111 | }; 112 | 113 | 114 | // backwards-compat 115 | WriteStream.prototype.cursorTo = function(x, y) { 116 | require('readline').cursorTo(this, x, y); 117 | }; 118 | WriteStream.prototype.moveCursor = function(dx, dy) { 119 | require('readline').moveCursor(this, dx, dy); 120 | }; 121 | WriteStream.prototype.clearLine = function(dir) { 122 | require('readline').clearLine(this, dir); 123 | }; 124 | WriteStream.prototype.clearScreenDown = function() { 125 | require('readline').clearScreenDown(this); 126 | }; 127 | WriteStream.prototype.getWindowSize = function() { 128 | return [this.columns, this.rows]; 129 | }; 130 | -------------------------------------------------------------------------------- /commonjs/lib/vm.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var binding = process.binding('contextify'); 23 | var Script = binding.ContextifyScript; 24 | var util = require('util'); 25 | 26 | // The binding provides a few useful primitives: 27 | // - ContextifyScript(code, { filename = "evalmachine.anonymous", 28 | // displayErrors = true } = {}) 29 | // with methods: 30 | // - runInThisContext({ displayErrors = true } = {}) 31 | // - runInContext(sandbox, { displayErrors = true, timeout = undefined } = {}) 32 | // - makeContext(sandbox) 33 | // - isContext(sandbox) 34 | // From this we build the entire documented API. 35 | 36 | Script.prototype.runInNewContext = function(sandbox, options) { 37 | var context = exports.createContext(sandbox); 38 | return this.runInContext(context, options); 39 | }; 40 | 41 | exports.Script = Script; 42 | 43 | exports.createScript = function(code, options) { 44 | return new Script(code, options); 45 | }; 46 | 47 | exports.createContext = function(sandbox) { 48 | if (util.isUndefined(sandbox)) { 49 | sandbox = {}; 50 | } else if (binding.isContext(sandbox)) { 51 | return sandbox; 52 | } 53 | 54 | binding.makeContext(sandbox); 55 | return sandbox; 56 | }; 57 | 58 | exports.runInContext = function(code, contextifiedSandbox, options) { 59 | var script = new Script(code, options); 60 | return script.runInContext(contextifiedSandbox, options); 61 | }; 62 | 63 | exports.runInNewContext = function(code, sandbox, options) { 64 | var script = new Script(code, options); 65 | return script.runInNewContext(sandbox, options); 66 | }; 67 | 68 | exports.runInThisContext = function(code, options) { 69 | var script = new Script(code, options); 70 | return script.runInThisContext(options); 71 | }; 72 | 73 | exports.isContext = binding.isContext; 74 | -------------------------------------------------------------------------------- /commonjs/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | templates/require.qml 4 | lib/_debugger.js 5 | lib/_http_agent.js 6 | lib/_http_client.js 7 | lib/_http_common.js 8 | lib/_http_incoming.js 9 | lib/_http_outgoing.js 10 | lib/_http_server.js 11 | lib/_linklist.js 12 | lib/_stream_duplex.js 13 | lib/_stream_passthrough.js 14 | lib/_stream_readable.js 15 | lib/_stream_transform.js 16 | lib/_stream_writable.js 17 | lib/_tls_legacy.js 18 | lib/_tls_wrap.js 19 | lib/assert.js 20 | lib/buffer.js 21 | lib/child_process.js 22 | lib/cluster.js 23 | lib/console.js 24 | lib/constants.js 25 | lib/crypto.js 26 | lib/dgram.js 27 | lib/dns.js 28 | lib/domain.js 29 | lib/events.js 30 | lib/freelist.js 31 | lib/fs.js 32 | lib/http.js 33 | lib/https.js 34 | lib/module.js 35 | lib/net.js 36 | lib/os.js 37 | lib/path.js 38 | lib/punycode.js 39 | lib/querystring.js 40 | lib/readline.js 41 | lib/repl.js 42 | lib/smalloc.js 43 | lib/stream.js 44 | lib/string_decoder.js 45 | lib/sys.js 46 | lib/timers.js 47 | lib/tls.js 48 | lib/tty.js 49 | lib/url.js 50 | lib/util.js 51 | lib/vm.js 52 | lib/zlib.js 53 | 54 | 55 | -------------------------------------------------------------------------------- /commonjs/templates/require.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0; 2 | 3 | QtObject { 4 | 5 | function requireInitializer( 6 | // this is a real parameter that is passed from C++ 7 | __native 8 | // these parameters are here to disallow access to global objects 9 | // with these names from inside CommonJS. If it is discovered 10 | // that some of them _are_ useful inside CommonJS, then a 11 | // separate CommonJS module, (e.g. "qml") should be defined 12 | // to provide this functionality. 13 | , Qt, gc, print, XMLHttpRequest, qsTr, qsTranslate, qsTrId 14 | , QT_TR_NOOP, QT_TRANSLATE_NOOP, QT_TRID_NOOP 15 | ) { 16 | ['setTimeout', 'clearTimeout', 17 | 'setInterval', 'clearInterval', 18 | 'process'].forEach(function(key){ 19 | __native.global[key] = __native[key]; 20 | }); 21 | 22 | // FIXME needs actual implementation 23 | function Buffer(){} 24 | 25 | var moduleSpecificLocals = ['__filename', '__dirname', 26 | 'module', 'exports']; 27 | 28 | // Creating a function responsible for requiring modules 29 | var __require = function(moduleSpecificLocals, __filename, parentModule) { 30 | 31 | // Making sure we have fully resolved path 32 | // because it's later use in cache lookup 33 | __filename = __native.resolve( 34 | __filename, parentModule ? parentModule.id : null); 35 | 36 | // if filename couldn't be resolved 37 | if(__filename instanceof Error) { 38 | throw __filename; 39 | } 40 | 41 | // first checking cache 42 | if(__native.cache[__filename]) { 43 | return __native.cache[__filename].exports; 44 | } 45 | 46 | // Setting up expected global variables 47 | // except for 'require', 'process' and Buffer 48 | // that require special treatment 49 | var __dirname = __filename.replace(/\/[^\/]*$/, ''); 50 | var global = __native.global; 51 | 52 | var exports = {}; 53 | var module = { 54 | id: __filename, 55 | exports: exports, 56 | loaded: false, 57 | parent: parentModule, 58 | children: [] 59 | }; 60 | 61 | // Adding this module as a child of parent modules 62 | if(parentModule) { 63 | parentModule.children.push(module); 64 | } 65 | 66 | // for nested require calls we need to adjust 67 | // base path so that relative require calls work 68 | var require = (function(module, url) { 69 | return __require.call(global, url, module); 70 | }).bind(global, module); 71 | 72 | // Providing require globals described here: 73 | // http://nodejs.org/api/globals.html#globals_require 74 | require.cache = __native.cache; 75 | require.resolve = function(url, parent){ 76 | var result = __native.resolve.apply(this, arguments); 77 | if(result instanceof Error) { 78 | throw result; 79 | } 80 | return result; 81 | }; 82 | 83 | // Making new require available in module object 84 | // http://nodejs.org/api/modules.html#modules_module_require_id 85 | module.require = require; 86 | 87 | // Adding to cache right away to deal with cyclic dependencies 88 | require.cache[__filename] = module; 89 | 90 | // creating a snippet of code that would expose registered 91 | // globals as local variables 92 | // 93 | // FIXME need to think of a way to mirror changes to local 94 | // vars into global and vice versa 95 | var globalFixSnippet = ""; 96 | Object.keys(global).forEach(function(key){ 97 | if(moduleSpecificLocals.indexOf(key) === -1) { 98 | globalFixSnippet += "var " + key + " = global." + key + ";"; 99 | } 100 | }); 101 | 102 | // now in the same manner exposing module-specific 103 | // local vars as global object properties 104 | moduleSpecificLocals.forEach(function(key){ 105 | globalFixSnippet += "global." + key + " = " + key +";"; 106 | }); 107 | 108 | // Applying fixes 109 | // @disable-check M23 // allowing eval 110 | eval(globalFixSnippet); 111 | 112 | // Cleaning namespace before code evaluation 113 | parentModule = undefined; 114 | moduleSpecificLocals = undefined; 115 | 116 | if(__filename.match(/\.json$/)) { 117 | module.exports = JSON.parse(__native.__loadFile(__filename)); 118 | } else { 119 | try { 120 | // Evaluating require'd code. Not using QJSEngine::evaluate 121 | // to allow exceptions when requiring modules to naturally 122 | // bubble up whereas QJSEngine::evaluate would simply return 123 | // the error instead of bubbling it calling code because 124 | // of necessary C++ calls. 125 | // 126 | // Additionally we have to wrap into an anonymous function 127 | // because if code contains a top-level function who's name 128 | // is the same as one of the properties on global object, 129 | // e.g. hasOwnProperty, then it is considered a write to that 130 | // property and thus results in an error. 131 | // 132 | // @disable-check M23 // allowing eval 133 | eval("try{(function () {" + 134 | __native.__loadFile(__filename) + 135 | // there is probably a bug that will not propagate exception 136 | // thrown inside eval() unless it's an instance of Error 137 | "}())}catch(e){ throw e instanceof Error ? e : new Error(e); }" 138 | ); 139 | } catch(e) { 140 | // Capturing stack trace. Unfortunately lineNumber is wrong with eval 141 | e.message += '\n ' + __filename /* + ':' + e.lineNumber */; 142 | throw e; 143 | } 144 | } 145 | // Marking module as loaded 146 | module.loaded = true; 147 | 148 | // Providing user with the result 149 | return module.exports; 150 | }; 151 | 152 | // Making sure __require is always executed in CommonJS 153 | // global context and not in QML global JS context 154 | __require = __require.bind(__native.global, moduleSpecificLocals); 155 | 156 | return __require; 157 | } 158 | 159 | function createFsStatsConstructor() { 160 | function Stats() {} 161 | 162 | Stats.prototype = { 163 | dev: 0, 164 | mode: 0, 165 | nlink: 0, 166 | uid: 0, 167 | gid: 0, 168 | rdev: 0, 169 | blksize: 0, 170 | ino: 0, 171 | size: 0, 172 | blocks: 0, 173 | atime: 0, 174 | mtime: 0, 175 | ctime: 0 176 | }; 177 | 178 | return Stats; 179 | } 180 | 181 | function resolveInitializer(__native) { 182 | 183 | var builtInModules = ["_degugger", "_http_agent", "http_client", 184 | "_http_common", "_http_incoming", "_http_outgoing", 185 | "_http_server", "_linklist", "_stream_duplex", 186 | "_stream_passthrough", "_stream_readable", 187 | "_stream_transform", "_stream_writable", 188 | "_tls_legacy", "_tls_wrap", 189 | "assert", "buffer", "child_process", "cluster", 190 | "console", "constants", "crypto", "dgram", "dns", 191 | "domain", "events", "freelist", "fs", "http", 192 | "https", "module", "net", "os", "path", 193 | "punycode", "querystring", "readline", "repl", 194 | "smalloc", "stream", "string_decoder", 195 | "sys", "timers", "tls", "tty", "url", "util", 196 | "vm", "zlib"]; 197 | 198 | function checkModuleAsDirectory(module) { 199 | if(module.slice(-3) === ".js" || module.slice(-5) === ".json") { 200 | return module; 201 | } 202 | 203 | var packagePath = module + "/package.json"; 204 | var mainFileName = "index.js"; 205 | var fs = __native.require('fs'); 206 | if(fs.existsSync(packagePath)) { 207 | var json = JSON.parse(__native.__loadFile(packagePath)); 208 | if(json.main) { 209 | mainFileName = json.main; 210 | } 211 | } 212 | 213 | return module + "/" + mainFileName; 214 | } 215 | 216 | // Creating a function responsible for requiring modules 217 | var __resolve = function(module, basePath) { 218 | 219 | // removing trimming end slash, file:// prefix and reducing to basename 220 | basePath = basePath.replace(/^file:\/\/|\/$|\/[^.\/\\]+\.js(on)?$/gi, ''); 221 | 222 | // Shortcurcuiting for built-in modules 223 | if(builtInModules.indexOf(module) > -1) { 224 | return ":lib/" + module + ".js"; 225 | } 226 | 227 | var path = __native.require('path'); 228 | var fs = __native.require('fs'); 229 | 230 | // removing prefix from file urls if present 231 | if(module.slice(0, 7) === "file://") { 232 | module = module.slice(7); 233 | } 234 | 235 | 236 | // relative path 237 | if(module.slice(0, 2) === "./" || module.slice(0, 3) === "../") { 238 | module = path.normalize(basePath + "/" + module); 239 | module = checkModuleAsDirectory(module); 240 | } else { 241 | // recursive upwards search in node_modules folders 242 | if(module[0] !== "/" && module.slice(0, 2) !== ":/") { 243 | var previousPath, currentPath; 244 | while(previousPath !== basePath) { 245 | currentPath = basePath + "/node_modules/" + module; 246 | currentPath = checkModuleAsDirectory(currentPath); 247 | if(currentPath !== module && fs.existsSync(currentPath)) { 248 | module = currentPath; 249 | break; 250 | } 251 | previousPath = basePath; 252 | basePath = path.normalize(basePath + '/..'); 253 | } 254 | } else { 255 | module = checkModuleAsDirectory(module); 256 | } 257 | } 258 | 259 | if(!fs.existsSync(module)) { 260 | return ""; 261 | } 262 | 263 | return module; 264 | }; 265 | 266 | // Making sure __resolve is always executed in CommonJS 267 | // global context and not in QML global JS context 268 | __resolve = __resolve.bind(__native.global); 269 | 270 | return __resolve; 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /plugin/commonjs_plugin.cpp: -------------------------------------------------------------------------------- 1 | #include "commonjs_plugin.h" 2 | #include "commonjs.h" 3 | 4 | #include 5 | 6 | void CommonJSPlugin::registerTypes(const char *uri) 7 | { 8 | Q_INIT_RESOURCE(resources); 9 | CommonJS::registerQmlSingletonType(uri); 10 | } 11 | 12 | CommonJSPlugin::~CommonJSPlugin() 13 | { 14 | Q_CLEANUP_RESOURCE(resources); 15 | } 16 | 17 | 18 | -------------------------------------------------------------------------------- /plugin/commonjs_plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGIN_PLUGIN_H 2 | #define PLUGIN_PLUGIN_H 3 | 4 | #include 5 | 6 | class CommonJSPlugin : public QQmlExtensionPlugin 7 | { 8 | Q_OBJECT 9 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") 10 | 11 | public: 12 | void registerTypes(const char *uri); 13 | ~CommonJSPlugin(); 14 | 15 | }; 16 | 17 | #endif // PLUGIN_PLUGIN_H 18 | 19 | -------------------------------------------------------------------------------- /plugin/plugin.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = lib 2 | TARGET = plugin 3 | QT += qml quick 4 | CONFIG += qt plugin 5 | 6 | TARGET = $$qtLibraryTarget($$TARGET) 7 | uri = CommonJS 8 | 9 | # Input 10 | SOURCES += \ 11 | commonjs_plugin.cpp 12 | 13 | HEADERS += \ 14 | commonjs_plugin.h 15 | 16 | OTHER_FILES = qmldir 17 | 18 | include(../commonjs/commonjs.pri) 19 | 20 | !equals(_PRO_FILE_PWD_, $$OUT_PWD) { 21 | copy_qmldir.target = $$OUT_PWD/qmldir 22 | copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir 23 | copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\" 24 | QMAKE_EXTRA_TARGETS += copy_qmldir 25 | PRE_TARGETDEPS += $$copy_qmldir.target 26 | } 27 | 28 | qmldir.files = qmldir 29 | unix { 30 | installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /) 31 | qmldir.path = $$installPath 32 | target.path = $$installPath 33 | INSTALLS += target qmldir 34 | } 35 | 36 | -------------------------------------------------------------------------------- /plugin/qmldir: -------------------------------------------------------------------------------- 1 | module CommonJS 2 | plugin plugin 3 | 4 | -------------------------------------------------------------------------------- /tests/commonjs-tests.pro: -------------------------------------------------------------------------------- 1 | QT += qml 2 | QT -= gui 3 | 4 | CONFIG += console 5 | CONFIG -= app_bundle 6 | 7 | # Add more folders to ship with the application, here 8 | qml_folder.source = qml 9 | qml_folder.target = . 10 | js_folder.source = js 11 | js_folder.target = . 12 | node_modules_folder.source = node_modules 13 | node_modules_folder.target = . 14 | DEPLOYMENTFOLDERS = qml_folder js_folder node_modules_folder 15 | 16 | MAINPROFILEPWD = $$PWD 17 | 18 | # Necessary to copy files to build folder. 19 | # Adapted for console from qtquick2applicationviewer. 20 | copyCommand = 21 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 22 | source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) 23 | source = $$replace(source, \\\\, /) 24 | target = $$OUT_PWD/$$eval($${deploymentfolder}.target) 25 | target = $$replace(target, \\\\, /) 26 | sourcePathSegments = $$split(source, /) 27 | targetFullPath = $$target/$$last(sourcePathSegments) 28 | targetFullPath ~= s,/\\.?/,/, 29 | !isEqual(source,$$targetFullPath) { 30 | !isEmpty(copyCommand):copyCommand += && 31 | copyCommand += $(MKDIR) \"$$target\" 32 | copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\" 33 | } 34 | } 35 | !isEmpty(copyCommand) { 36 | copyCommand = @echo Copying application data... && $$copyCommand 37 | copydeploymentfolders.commands = $$copyCommand 38 | first.depends = $(first) copydeploymentfolders 39 | export(first.depends) 40 | export(copydeploymentfolders.commands) 41 | QMAKE_EXTRA_TARGETS += first copydeploymentfolders 42 | } 43 | !isEmpty(target.path) { 44 | installPrefix = $${target.path} 45 | } else { 46 | installPrefix = /opt/$${TARGET} 47 | } 48 | for(deploymentfolder, DEPLOYMENTFOLDERS) { 49 | item = item$${deploymentfolder} 50 | itemfiles = $${item}.files 51 | $$itemfiles = $$eval($${deploymentfolder}.source) 52 | itempath = $${item}.path 53 | $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target) 54 | export($$itemfiles) 55 | export($$itempath) 56 | INSTALLS += $$item 57 | } 58 | 59 | isEmpty(target.path) { 60 | target.path = $${installPrefix}/bin 61 | export(target.path) 62 | } 63 | INSTALLS += target 64 | 65 | # Additional import path used to resolve QML modules in Creator's code model 66 | QML_IMPORT_PATH = 67 | 68 | # The .cpp file which was generated for your project. Feel free to hack it. 69 | SOURCES += main.cpp 70 | 71 | include(../commonjs/commonjs.pri) 72 | 73 | OTHER_FILES += \ 74 | js/main.js 75 | 76 | HEADERS += 77 | 78 | -------------------------------------------------------------------------------- /tests/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | console.log('Start Testing. Version: ' + process.version + 2 | ". Platform: " + process.platform); 3 | 4 | // file doesn't exist 5 | try { 6 | var main = require.resolve('./non-existent-file.js'); 7 | } catch(e) { 8 | console.log("Non-existent modules throw Errors as expected."); 9 | } 10 | 11 | // error inside file 12 | try { 13 | var main = require('./main.js'); 14 | } catch(e) { 15 | console.log("Catching require error works"); 16 | } 17 | 18 | var assert = require('assert'); 19 | 20 | try { 21 | ['path', 'querystring', 'events', 22 | 'punycode', 'url', 'freelist'].forEach(function(module){ 23 | assert.ok(require(module)); 24 | }); 25 | ['./no-package-json', './package-json', 26 | 'testmodule', 'inparentfolder'].forEach(function(module){ 27 | assert.equal("works", require(module)); 28 | }); 29 | assert.equal("works", require('./config.json').somekey); 30 | } catch(e) { 31 | console.error(e); 32 | } 33 | 34 | console.log('All done.'); 35 | -------------------------------------------------------------------------------- /tests/js/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "somekey": "works" 3 | } 4 | -------------------------------------------------------------------------------- /tests/js/main.js: -------------------------------------------------------------------------------- 1 | throw 'test error' 2 | -------------------------------------------------------------------------------- /tests/js/no-package-json/index.js: -------------------------------------------------------------------------------- 1 | module.exports = "works"; 2 | -------------------------------------------------------------------------------- /tests/js/node_modules/testmodule/custom-main-file.js: -------------------------------------------------------------------------------- 1 | module.exports = "works"; 2 | -------------------------------------------------------------------------------- /tests/js/node_modules/testmodule/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-package-json", 3 | "main": "custom-main-file.js" 4 | } 5 | -------------------------------------------------------------------------------- /tests/js/package-json/custom-main-file.js: -------------------------------------------------------------------------------- 1 | module.exports = "works"; 2 | -------------------------------------------------------------------------------- /tests/js/package-json/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-package-json", 3 | "main": "custom-main-file.js" 4 | } 5 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "commonjs.h" 3 | 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QCoreApplication app(argc, argv); 10 | CommonJS::registerQmlSingletonType(); 11 | 12 | QQmlEngine *engine = new QQmlEngine; 13 | engine->setBaseUrl(QUrl::fromLocalFile(qApp->applicationDirPath())); 14 | qApp->connect(engine, SIGNAL(quit()), qApp, SLOT(quit())); 15 | 16 | QUrl url = QUrl::fromLocalFile(QFileInfo("qml/main.qml").absoluteFilePath()); 17 | QQmlComponent mainQml(engine, url); 18 | mainQml.loadUrl(url); 19 | mainQml.create(); 20 | 21 | // The only way component isn't ready is if something went wrong 22 | if(!mainQml.isReady() || mainQml.isError()) { 23 | qDebug() << mainQml.errors(); 24 | return -1; 25 | } 26 | 27 | return app.exec(); 28 | } 29 | -------------------------------------------------------------------------------- /tests/node_modules/inparentfolder/custom-main-file.js: -------------------------------------------------------------------------------- 1 | module.exports = "works"; 2 | -------------------------------------------------------------------------------- /tests/node_modules/inparentfolder/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-package-json", 3 | "main": "custom-main-file.js" 4 | } 5 | -------------------------------------------------------------------------------- /tests/qml/main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import CommonJS 0.2 3 | 4 | QtObject { 5 | 6 | Component.onCompleted: { 7 | CommonJS.require('./js/bootstrap.js'); 8 | var i = 1; 9 | var intervalId = CommonJS.setInterval(function(){ 10 | console.log('Interval call ' + i); 11 | if(++i > 5) { 12 | CommonJS.clearInterval(intervalId); 13 | } 14 | }, 10); 15 | CommonJS.setTimeout(function(){ 16 | Qt.quit(); 17 | }, 100); 18 | } 19 | } 20 | --------------------------------------------------------------------------------