[Pkg-javascript-commits] [node-nan] 03/09: Imported Upstream version 1.8.4

Andrew Kelley andrewrk-guest at moszumanska.debian.org
Mon May 18 20:19:18 UTC 2015


This is an automated email from the git hooks/post-receive script.

andrewrk-guest pushed a commit to branch master
in repository node-nan.

commit 8d7c5d5c16ea227797774ffc32abc353b8b3f843
Author: Andrew Kelley <superjoe30 at gmail.com>
Date:   Mon May 18 19:47:41 2015 +0000

    Imported Upstream version 1.8.4
---
 .travis.yml                            |   12 +-
 CHANGELOG.md                           |  146 +-
 LICENSE                                |   46 -
 LICENSE.md                             |   13 +
 Makefile                               |   29 +-
 README.md                              |  428 ++++-
 appveyor.yml                           |   24 +-
 cpplint.py                             | 3138 ++++++++++++++++++++++++--------
 examples/async_pi_estimate/addon.cc    |   13 +-
 examples/async_pi_estimate/addon.js    |    8 +
 examples/async_pi_estimate/async.cc    |   13 +-
 examples/async_pi_estimate/async.h     |    9 +-
 examples/async_pi_estimate/pi_est.cc   |   12 +-
 examples/async_pi_estimate/pi_est.h    |    8 +-
 examples/async_pi_estimate/sync.cc     |   13 +-
 examples/async_pi_estimate/sync.h      |    9 +-
 nan.h                                  | 1333 +++++++-------
 nan_implementation_12_inl.h            |  261 +++
 nan_implementation_pre_12_inl.h        |  267 +++
 nan_new.h                              |  328 ++++
 nan_string_bytes.h                     |  312 ++++
 package.json                           |   14 +-
 test/binding.gyp                       |   89 +-
 test/cpp/asyncprogressworker.cpp       |   66 +
 test/cpp/asyncworker.cpp               |    8 +-
 test/cpp/asyncworkererror.cpp          |    8 +-
 test/cpp/bufferworkerpersistent.cpp    |    8 +-
 test/cpp/gc.cpp                        |   38 +
 test/cpp/isolatedata.cpp               |    8 +-
 test/cpp/makecallback.cpp              |   14 +-
 test/cpp/morenews.cpp                  |   10 +-
 test/cpp/multifile1.cpp                |    8 +-
 test/cpp/multifile2.cpp                |    8 +-
 test/cpp/multifile2.h                  |    9 +-
 test/cpp/nancallback.cpp               |   52 +
 test/cpp/nannew.cpp                    |  502 +++++
 test/cpp/news.cpp                      |   56 +-
 test/cpp/objectwraphandle.cpp          |   61 +
 test/cpp/optionvalues.cpp              |    8 +-
 test/cpp/persistent.cpp                |   10 +-
 test/cpp/returnemptystring.cpp         |    8 +-
 test/cpp/returnnull.cpp                |    8 +-
 test/cpp/returnundefined.cpp           |    8 +-
 test/cpp/returnvalue.cpp               |   26 +-
 test/cpp/settemplate.cpp               |   14 +-
 test/cpp/settergetter.cpp              |    8 +-
 test/cpp/strings.cpp                   |   46 +-
 test/cpp/symbols.cpp                   |    8 +-
 test/cpp/threadlocal.cpp               |   68 +
 test/cpp/weak.cpp                      |    8 +-
 test/js/asyncprogressworker-test.js    |   23 +
 test/js/asyncworker-test.js            |    8 +
 test/js/asyncworkererror-test.js       |    8 +
 test/js/bufferworkerpersistent-test.js |    8 +
 test/js/gc-test.js                     |   23 +
 test/js/isolatedata-test.js            |    8 +
 test/js/makecallback-test.js           |    8 +
 test/js/morenews-test.js               |    8 +
 test/js/multifile-test.js              |    8 +
 test/js/nancallback-test.js            |   30 +
 test/js/nannew-test.js                 |   51 +
 test/js/news-test.js                   |   16 +-
 test/js/objectwraphandle-test.js       |   22 +
 test/js/optionvalues-test.js           |    8 +
 test/js/persistent-test.js             |    8 +
 test/js/returnemptystring-test.js      |    8 +
 test/js/returnnull-test.js             |    8 +
 test/js/returnundefined-test.js        |    8 +
 test/js/returnvalue-test.js            |   14 +-
 test/js/settemplate-test.js            |    8 +
 test/js/settergetter-test.js           |    8 +
 test/js/strings-test.js                |   13 +-
 test/js/symbols-test.js                |    8 +
 test/js/threadlocal-test.js            |   13 +
 test/js/weak-test.js                   |    8 +
 75 files changed, 6146 insertions(+), 1788 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index ca76fc3..5ea03f0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,10 @@
 language: node_js
 env:
   - NODE_VERSION="0.8"
-  - NODE_VERSION="0.10.27"
-  - NODE_VERSION="0.10.28"
-  - NODE_VERSION="0.10.29"
-  - NODE_VERSION="0.10.30"
-  - NODE_VERSION="0.11.13"
+  - NODE_VERSION="0.10"
+  - NODE_VERSION="0.12"
+  - NODE_VERSION="iojs"
+#  - NODE_WEBKIT="0.11.6" NODE_VERSION="0.11.13"
 node_js:
   - "0.10"
 notifications:
@@ -21,6 +20,7 @@ before_install:
   - source ~/.nvm/nvm.sh
   - nvm install $NODE_VERSION
   - node --version
-  - node_modules/.bin/node-gyp rebuild --directory test
+  - if [[ ${NODE_VERSION} == "0.8" ]]; then node_modules/.bin/node-gyp rebuild --directory test; else node_modules/.bin/pangyp rebuild --directory test; fi
+#  - if [[ ${NODE_WEBKIT:-unset} != "unset" ]]; then npm install nw-gyp && ./node_modules/.bin/nw-gyp rebuild --directory test --target=$NODE_WEBKIT; fi
 install:
 script: tap --gc test/js/*-test.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 146cbb5..8e8f052 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,103 @@
 # NAN ChangeLog
 
-### Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30
+**Version 1.8.4: current Node 12: 0.12.2, Node 10: 0.10.38, io.js: 1.8.1**
 
+### 1.8.4 Apr 26 2015
 
-**1.3.0 Aug 2 2014**
+  - Build: Repackage
+
+### 1.8.3 Apr 26 2015
+
+  - Bugfix: Include missing header 1af8648
+
+### 1.8.2 Apr 23 2015
+
+  - Build: Repackage
+
+### 1.8.1 Apr 23 2015
+
+  - Bugfix: NanObjectWrapHandle should take a pointer 155f1d3
+
+### 1.8.0 Apr 23 2015
+
+  - Feature: Allow primitives with NanReturnValue 2e4475e
+  - Feature: Added comparison operators to NanCallback 55b075e
+  - Feature: Backport thread local storage 15bb7fa
+  - Removal: Remove support for signatures with arguments 8a2069d
+  - Correcteness: Replaced NanObjectWrapHandle macro with function 0bc6d59
+
+### 1.7.0 Feb 28 2015
+
+  - Feature: Made NanCallback::Call accept optional target 8d54da7
+  - Feature: Support atom-shell 0.21 0b7f1bb
+
+### 1.6.2 Feb 6 2015
+
+  - Bugfix: NanEncode: fix argument type for node::Encode on io.js 2be8639
+
+### 1.6.1 Jan 23 2015
+
+  - Build: version bump
+
+### 1.5.3 Jan 23 2015
+
+  - Build: repackage
+
+### 1.6.0 Jan 23 2015
+
+ - Deprecated `NanNewContextHandle` in favor of `NanNew<Context>` 49259af
+ - Support utility functions moved in newer v8 versions (Node 0.11.15, io.js 1.0) a0aa179
+ - Added `NanEncode`, `NanDecodeBytes` and `NanDecodeWrite` 75e6fb9
+
+### 1.5.2 Jan 23 2015
+
+  - Bugfix: Fix non-inline definition build error with clang++ 21d96a1, 60fadd4
+  - Bugfix: Readded missing String constructors 18d828f
+  - Bugfix: Add overload handling NanNew<FunctionTemplate>(..) 5ef813b
+  - Bugfix: Fix uv_work_cb versioning 997e4ae
+  - Bugfix: Add function factory and test 4eca89c
+  - Bugfix: Add object template factory and test cdcb951
+  - Correctness: Lifted an io.js related typedef c9490be
+  - Correctness: Make explicit downcasts of String lengths 00074e6
+  - Windows: Limit the scope of disabled warning C4530 83d7deb
+
+### 1.5.1 Jan 15 2015
+
+  - Build: version bump
+
+### 1.4.3 Jan 15 2015
+
+  - Build: version bump
+
+### 1.4.2 Jan 15 2015
+
+  - Feature: Support io.js 0dbc5e8
+
+### 1.5.0 Jan 14 2015
+
+ - Feature: Support io.js b003843
+ - Correctness: Improved NanNew internals 9cd4f6a
+ - Feature: Implement progress to NanAsyncWorker 8d6a160
+
+### 1.4.1 Nov 8 2014
+
+ - Bugfix: Handle DEBUG definition correctly
+ - Bugfix: Accept int as Boolean
+
+### 1.4.0 Nov 1 2014
+
+ - Feature: Added NAN_GC_CALLBACK 6a5c245
+ - Performance: Removed unnecessary local handle creation 18a7243, 41fe2f8
+ - Correctness: Added constness to references in NanHasInstance 02c61cd
+ - Warnings: Fixed spurious warnings from -Wundef and -Wshadow, 541b122, 99d8cb6
+ - Windoze: Shut Visual Studio up when compiling 8d558c1
+ - License: Switch to plain MIT from custom hacked MIT license 11de983
+ - Build: Added test target to Makefile e232e46
+ - Performance: Removed superfluous scope in NanAsyncWorker f4b7821
+ - Sugar/Feature: Added NanReturnThis() and NanReturnHolder() shorthands 237a5ff, d697208
+ - Feature: Added suitable overload of NanNew for v8::Integer::NewFromUnsigned b27b450
+
+### 1.3.0 Aug 2 2014
 
  - Added NanNew<v8::String, std::string>(std::string)
  - Added NanNew<v8::String, std::string&>(std::string&)
@@ -21,7 +115,7 @@
  - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, const char *name, v8::Handle<v8::Data> value)
  - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
 
-**1.2.0 Jun 5 2014**
+### 1.2.0 Jun 5 2014
 
  - Add NanSetPrototypeTemplate
  - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class,
@@ -29,15 +123,15 @@
  - Removed -Wno-unused-local-typedefs from test builds
  - Made test builds Windows compatible ('Sleep()')
 
-**1.1.2 May 28 2014**
+### 1.1.2 May 28 2014
 
  - Release to fix more stuff-ups in 1.1.1
 
-**1.1.1 May 28 2014**
+### 1.1.1 May 28 2014
 
  - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0
 
-**1.1.0 May 25 2014**
+### 1.1.0 May 25 2014
 
  - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead
  - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]),
@@ -46,7 +140,7 @@
  - Deprecate NanSymbol()
  - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker
 
-**1.0.0 May 4 2014**
+### 1.0.0 May 4 2014
 
  - Heavy API changes for V8 3.25 / Node 0.11.13
  - Use cpplint.py
@@ -70,18 +164,18 @@
  - Introduce NanGetHeapStatistics
  - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent()
 
-**0.8.0 Jan 9 2014**
+### 0.8.0 Jan 9 2014
 
  - NanDispose -> NanDisposePersistent, deprecate NanDispose
  - Extract _NAN_*_RETURN_TYPE, pull up NAN_*()
 
-**0.7.1 Jan 9 2014**
+### 0.7.1 Jan 9 2014
 
  - Fixes to work against debug builds of Node
  - Safer NanPersistentToLocal (avoid reinterpret_cast)
  - Speed up common NanRawString case by only extracting flattened string when necessary
 
-**0.7.0 Dec 17 2013**
+### 0.7.0 Dec 17 2013
 
  - New no-arg form of NanCallback() constructor.
  - NanCallback#Call takes Handle rather than Local
@@ -92,58 +186,58 @@
      (replacement for NanFromV8String)
  - Introduce NanCString() for null-terminated char* from v8::String
 
-**0.6.0 Nov 21 2013**
+### 0.6.0 Nov 21 2013
 
  - Introduce NanNewLocal<T>(v8::Handle<T> value) for use in place of
      v8::Local<T>::New(...) since v8 started requiring isolate in Node 0.11.9
 
-**0.5.2 Nov 16 2013**
+### 0.5.2 Nov 16 2013
 
  - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public
 
-**0.5.1 Nov 12 2013**
+### 0.5.1 Nov 12 2013
 
  - Use node::MakeCallback() instead of direct v8::Function::Call()
 
-**0.5.0 Nov 11 2013**
+### 0.5.0 Nov 11 2013
 
  - Added @TooTallNate as collaborator
  - New, much simpler, "include_dirs" for binding.gyp
  - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros
 
-**0.4.4 Nov 2 2013**
+### 0.4.4 Nov 2 2013
 
  - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+
 
-**0.4.3 Nov 2 2013**
+### 0.4.3 Nov 2 2013
 
  - Include node_object_wrap.h, removed from node.h for Node 0.11.8.
 
-**0.4.2 Nov 2 2013**
+### 0.4.2 Nov 2 2013
 
  - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for
      Node 0.11.8 release.
 
-**0.4.1 Sep 16 2013**
+### 0.4.1 Sep 16 2013
 
  - Added explicit `#include <uv.h>` as it was removed from node.h for v0.11.8
 
-**0.4.0 Sep 2 2013**
+### 0.4.0 Sep 2 2013
 
  - Added NAN_INLINE and NAN_DEPRECATED and made use of them
  - Added NanError, NanTypeError and NanRangeError
  - Cleaned up code
 
-**0.3.2 Aug 30 2013**
+### 0.3.2 Aug 30 2013
 
  - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent
      in NanAsyncWorker
 
-**0.3.1 Aug 20 2013**
+### 0.3.1 Aug 20 2013
 
  - fix "not all control paths return a value" compile warning on some platforms
 
-**0.3.0 Aug 19 2013**
+### 0.3.0 Aug 19 2013
 
  - Made NAN work with NPM
  - Lots of fixes to NanFromV8String, pulling in features from new Node core
@@ -158,16 +252,16 @@
  - Changed NanThrowError(Local<Value>) to NanThrowError(Handle<Value>)
  - Fixed leak in NanAsyncWorker when errmsg is used
 
-**0.2.2 Aug 5 2013**
+### 0.2.2 Aug 5 2013
 
  - Fixed usage of undefined variable with node::BASE64 in NanFromV8String()
 
-**0.2.1 Aug 5 2013**
+### 0.2.1 Aug 5 2013
 
  - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for
      NanFromV8String()
 
-**0.2.0 Aug 5 2013**
+### 0.2.0 Aug 5 2013
 
  - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR,
      NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY
@@ -189,7 +283,7 @@
  - Added initial test suite (to be expanded)
  - Allow NanUInt32OptionValue to convert any Number object
 
-**0.1.0 Jul 21 2013**
+### 0.1.0 Jul 21 2013
 
  - Added `NAN_GETTER`, `NAN_SETTER`
  - Added `NanThrowError` with single Local<Value> argument
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index d502e18..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,46 +0,0 @@
-Copyright 2013, NAN contributors:
-  - Rod Vagg <https://github.com/rvagg>
-  - Benjamin Byholm <https://github.com/kkoopa>
-  - Trevor Norris <https://github.com/trevnorris>
-  - Nathan Rajlich <https://github.com/TooTallNate>
-  - Brett Lawson <https://github.com/brett19>
-  - Ben Noordhuis <https://github.com/bnoordhuis>
-(the "Original Author")
-All rights reserved.
-
-MIT +no-false-attribs License
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-Distributions of all or part of the Software intended to be used
-by the recipients as they would use the unmodified Software,
-containing modifications that substantially alter, remove, or
-disable functionality of the Software, outside of the documented
-configuration mechanisms provided by the Software, shall be
-modified such that the Original Author's bug reporting email
-addresses and urls are either replaced with the contact information
-of the parties responsible for the changes, or removed entirely.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-
-Except where noted, this license applies to any and all software
-programs and associated documentation files created by the
-Original Author, when distributed with the Software.
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..95c2eb5
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,13 @@
+The MIT License (MIT)
+=====================
+
+Copyright (c) 2015 NAN contributors
+-----------------------------------
+
+*NAN contributors listed at <https://github.com/rvagg/nan#contributors>*
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Makefile b/Makefile
index ea51185..fab1204 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,12 @@
 TOPLEVEL ?= $(dir $(lastword $(MAKEFILE_LIST)))
 CPPLINT ?= $(TOPLEVEL)/cpplint.py
 PYTHON ?= python
+BUILDTYPE ?= Release
+MODULES = symbols strings optionvalues
+SOURCES = $(MODULES:%=test/cpp/%.cpp)
+ADDONS = $(MODULES:%=test/build/$(BUILDTYPE)/%.node)
 
-SOURCES = \
+LINT_SOURCES = \
 	examples/async_pi_estimate/addon.cc \
 	examples/async_pi_estimate/async.cc \
 	examples/async_pi_estimate/async.h \
@@ -11,14 +15,23 @@ SOURCES = \
 	examples/async_pi_estimate/sync.cc \
 	examples/async_pi_estimate/sync.h \
 	nan.h \
+	nan_string_bytes.h \
+	nan_implementation_12_inl.h \
+	nan_implementation_pre_12_inl.h \
+	nan_new.h \
 	test/cpp/asyncworker.cpp \
+        test/cpp/asyncprogressworker.cpp \
         test/cpp/asyncworkererror.cpp \
         test/cpp/bufferworkerpersistent.cpp \
+        test/cpp/gc.cpp \
         test/cpp/morenews.cpp \
 	test/cpp/multifile1.cpp \
 	test/cpp/multifile2.cpp \
 	test/cpp/multifile2.h \
+	test/cpp/nancallback.cpp \
+	test/cpp/nannew.cpp \
         test/cpp/news.cpp \
+	test/cpp/objectwraphandle.cpp \
 	test/cpp/optionvalues.cpp \
 	test/cpp/persistent.cpp \
 	test/cpp/returnemptystring.cpp \
@@ -29,11 +42,21 @@ SOURCES = \
 	test/cpp/strings.cpp \
 	test/cpp/symbols.cpp \
         test/cpp/weak.cpp \
-	test/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc
+	node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc
 
 FILTER = -whitespace/parens
 
 .PHONY: lint
 
 lint:
-	cd $(TOPLEVEL) && $(PYTHON) $(CPPLINT) --filter=$(FILTER) $(SOURCES)
+	cd $(TOPLEVEL) && $(PYTHON) $(CPPLINT) --filter=$(FILTER) $(LINT_SOURCES)
+
+test: $(ADDONS)
+	npm test
+
+forcetest:
+	cd test/ && node-gyp rebuild && cd ..
+	npm test
+
+$(ADDONS): nan.h nan_string_bytes.h nan_new.h nan_implementation_pre_12_inl.h nan_implementation_12_inl.h test/binding.gyp $(SOURCES)
+	cd test/ && ../node_modules/.bin/node-gyp rebuild
diff --git a/README.md b/README.md
index 2904a38..26f6947 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,18 @@
 Native Abstractions for Node.js
 ===============================
 
-**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.**
+**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.12 as well as io.js.**
 
-***Current version: 1.3.0***
+***Current version: 1.8.4***
 
-*(See [nan.h](https://github.com/rvagg/nan/blob/master/CHANGELOG.md) for complete ChangeLog)*
+*(See [CHANGELOG.md](https://github.com/iojs/nan/blob/master/CHANGELOG.md) for complete ChangeLog)*
 
-[![NPM](https://nodei.co/npm/nan.png?downloads=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/)
+[![NPM](https://nodei.co/npm/nan.png?downloads=true&downloadRank=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6&height=3)](https://nodei.co/npm/nan/)
 
-[![Build Status](https://secure.travis-ci.org/rvagg/nan.png)](http://travis-ci.org/rvagg/nan)
+[![Build Status](https://api.travis-ci.org/iojs/nan.svg?branch=master)](http://travis-ci.org/iojs/nan)
 [![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan)
 
-Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle.
+Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle.
 
 This project also contains some helper utilities that make addon development a bit more pleasant.
 
@@ -20,10 +20,39 @@ This project also contains some helper utilities that make addon development a b
  * **[Usage](#usage)**
  * **[Example](#example)**
  * **[API](#api)**
+ * **[Tests](#tests)**
+ * **[Porting](#porting)**
+ * **[Governance & Contributing](#governance)**
 
 <a name="news"></a>
 ## News & Updates
 
+### Apr-2015: 1.8.0 release
+
+* Support V8 4.2
+* Removed support for creating `Signature`s with arguments
+* Backported thread local storage routines for libuv
+
+### Feb-2015: 1.7.0 release
+
+* Made `NanCallback::Call` accept optional target
+* Support atom-shell 0.21
+
+Node 0.12.0 is out and supported by NAN. So is atom-shell 0.21. `NanCallback::Call` now accepts an optional `target` argument like `NanMakeCallback`.
+
+### Jan-2015: 1.6.0 release
+
+* Deprecated `NanNewContextHandle` in favor of `NanNew<Context>`
+* Added `NanSetCounterFunction`, `NanSetCreateHistogramFunction`, `NanSetAddHistogramSampleFunction`
+* Added `NanIdleNotification`, `NanLowMemoryNotification`, `NanContextDisposedNotification`
+* Added `NanEncode`, `NanDecodeBytes` and `NanDecodeWrite`
+
+### Jan-2015: 1.5.0 release
+
+* Support [io.js](https://github.com/iojs/io.js) thanks to [Ben Noordhuis](bnoordhuis)
+* Rewritten NanNew internals thanks to [David Siegel](agnat)
+* NanAsyncWorker now supports progress reporting thanks to [Brett Lawson](brett19)
+
 ### Aug-2014: 1.3.0 release
 
 * `NanCString()` and `NanRawString()` have been deprecated in favour of new <a href="#api_nan_ascii_string"><b><code>NanAsciiString</code></b></a>, <a href="#api_nan_utf8_string"><b><code>NanUtf8String</code></b></a> and <a href="#api_nan_ucs2_string"><b><code>NanUcs2String</code></b></a>. These classes manage the underlying memory for you in a safer way than just handing off an allocated array. You should now `*NanAsciiString(handle)` to access the raw `char` data, you can also allocate [...]
@@ -58,7 +87,7 @@ V8 has now introduced an `EscapableHandleScope` from which you `scope.Escape(Loc
 
 Because `node::MakeCallback()` now takes an `Isolate`, and because it doesn't exist in older versions of Node, we've introduced `NanMakeCallback()`. You should *always* use this when calling a JavaScript function from C++.
 
-There's lots more, check out the Changelog in nan.h or look through [#86](https://github.com/rvagg/nan/pull/86) for all the gory details.
+There's lots more, check out the Changelog in nan.h or look through [#86](https://github.com/iojs/nan/pull/86) for all the gory details.
 
 ### Dec-2013: NanCString and NanRawString
 
@@ -98,9 +127,11 @@ This works like a `-I<path-to-NAN>` when compiling your addon.
 
 See **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use.
 
-For a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**.
+For a simpler example, see the **[async pi estimation example](https://github.com/iojs/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**.
 
-Compare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work).
+For another example, see **[nan-example-eol](https://github.com/CodeCharmLtd/nan-example-eol)**. It shows newline detection implemented as a native addon.
+
+Compare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/iojs/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work).
 
 Note that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class.
 
@@ -238,6 +269,7 @@ NAN_METHOD(CalculateAsync) {
  * <a href="#api_nan_index_enumerator"><b><code>NAN_INDEX_ENUMERATOR</code></b></a>
  * <a href="#api_nan_index_deleter"><b><code>NAN_INDEX_DELETER</code></b></a>
  * <a href="#api_nan_index_query"><b><code>NAN_INDEX_QUERY</code></b></a>
+ * <a href="#api_nan_gc_callback"><b><code>NAN_GC_CALLBACK</code></b></a>
  * <a href="#api_nan_weak_callback"><b><code>NAN_WEAK_CALLBACK</code></b></a>
  * <a href="#api_nan_deprecated"><b><code>NAN_DEPRECATED</code></b></a>
  * <a href="#api_nan_inline"><b><code>NAN_INLINE</code></b></a>
@@ -250,6 +282,8 @@ NAN_METHOD(CalculateAsync) {
  * <a href="#api_nan_return_undefined"><b><code>NanReturnUndefined</code></b></a>
  * <a href="#api_nan_return_null"><b><code>NanReturnNull</code></b></a>
  * <a href="#api_nan_return_empty_string"><b><code>NanReturnEmptyString</code></b></a>
+ * <a href="#api_nan_return_this"><b><code>NanReturnThis</code></b></a>
+ * <a href="#api_nan_return_holder"><b><code>NanReturnHolder</code></b></a>
  * <a href="#api_nan_scope"><b><code>NanScope</code></b></a>
  * <a href="#api_nan_escapable_scope"><b><code>NanEscapableScope</code></b></a>
  * <a href="#api_nan_escape_scope"><b><code>NanEscapeScope</code></b></a>
@@ -272,7 +306,7 @@ NAN_METHOD(CalculateAsync) {
  * <a href="#api_nan_throw_error"><b><code>NanThrowError</code></b>, <b><code>NanThrowTypeError</code></b>, <b><code>NanThrowRangeError</code></b>, <b><code>NanThrowError(Handle<Value>)</code></b>, <b><code>NanThrowError(Handle<Value>, int)</code></b></a>
  * <a href="#api_nan_new_buffer_handle"><b><code>NanNewBufferHandle(char *, size_t, FreeCallback, void *)</code></b>, <b><code>NanNewBufferHandle(char *, uint32_t)</code></b>, <b><code>NanNewBufferHandle(uint32_t)</code></b></a>
  * <a href="#api_nan_buffer_use"><b><code>NanBufferUse(char *, uint32_t)</code></b></a>
- * <a href="#api_nan_new_context_handle"><b><code>NanNewContextHandle</code></b></a>
+ * <del><a href="#api_nan_new_context_handle"><b><code>NanNewContextHandle</code></b></a></del>
  * <a href="#api_nan_get_current_context"><b><code>NanGetCurrentContext</code></b></a>
  * <a href="#api_nan_has_instance"><b><code>NanHasInstance</code></b></a>
  * <a href="#api_nan_dispose_persistent"><b><code>NanDisposePersistent</code></b></a>
@@ -282,6 +316,9 @@ NAN_METHOD(CalculateAsync) {
  * <a href="#api_nan_set_prototype_template"><b><code>NanSetPrototypeTemplate</code></b></a>
  * <a href="#api_nan_set_instance_template"><b><code>NanSetInstanceTemplate</code></b></a>
  * <a href="#api_nan_make_callback"><b><code>NanMakeCallback</code></b></a>
+ * <a href="#api_nan_encode"><b><code>NanEncode</code></b></a>
+ * <a href="#api_nan_decode_bytes"><b><code>NanDecodeBytes</code></b></a>
+ * <a href="#api_nan_decode_write"><b><code>NanDecodeWrite</code></b></a>
  * <a href="#api_nan_compile_script"><b><code>NanCompileScript</code></b></a>
  * <a href="#api_nan_run_script"><b><code>NanRunScript</code></b></a>
  * <a href="#api_nan_adjust_external_memory"><b><code>NanAdjustExternalMemory</code></b></a>
@@ -290,6 +327,12 @@ NAN_METHOD(CalculateAsync) {
  * <a href="#api_nan_remove_gc_epilogue_callback"><b><code>NanRemoveGCEpilogueCallback</code></b></a>
  * <a href="#api_nan_remove_gc_prologue_callback"><b><code>NanRemoveGCPrologueCallback</code></b></a>
  * <a href="#api_nan_get_heap_statistics"><b><code>NanGetHeapStatistics</code></b></a>
+ * <a href="#api_nan_set_counter_function"><b><code>NanSetCounterFunction</code></b></a>
+ * <a href="#api_nan_set_create_histogram_function"><b><code>NanSetCreateHistogramFunction</code></b></a>
+ * <a href="#api_nan_set_add_histogram_sample_function"><b><code>NanSetAddHistogramSampleFunction</code></b></a>
+ * <a href="#api_nan_idle_notification"><b><code>NanIdleNotification</code></b></a>
+ * <a href="#api_nan_low_memory_notification"><b><code>NanLowMemoryNotification</code></b></a>
+ * <a href="#api_nan_context_disposed_notification"><b><code>NanContextDisposedNotification</code></b></a>
  * <a href="#api_nan_callback"><b><code>NanCallback</code></b></a>
  * <a href="#api_nan_async_worker"><b><code>NanAsyncWorker</code></b></a>
  * <a href="#api_nan_async_queue_worker"><b><code>NanAsyncQueueWorker</code></b></a>
@@ -399,6 +442,26 @@ Use `NAN_INDEX_QUERY` to declare your V8 accessible index queries. Same as `NAN_
 
 You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_QUERY`.
 
+<a name="api_nan_gc_callback"></a>
+### NAN_GC_CALLBACK(cbname)
+Use `NAN_GC_CALLBACK` to declare your callbacks for `NanAddGCEpilogueCallback` and `NanAddGCPrologueCallback`. You get arguments `GCType type` and `GCCallbackFlags flags`.
+
+```c++
+static Persistent<Function> callback;
+
+NAN_GC_CALLBACK(gcPrologueCallback) {
+  Local<Value> argv[] = {NanNew("prologue")};
+  NanMakeCallback(NanGetCurrentContext()->Global(), NanNew(callback), 1, argv);
+}
+
+NAN_METHOD(Hook) {
+  NanScope();
+  NanAssignPersistent(callback, args[0].As<Function>());
+  NanAddGCPrologueCallback(gcPrologueCallback);
+  NanReturnValue(args.Holder());
+}
+```
+
 <a name="api_nan_weak_callback"></a>
 ### NAN_WEAK_CALLBACK(cbname)
 
@@ -439,13 +502,7 @@ NAN_INLINE int foo(int bar) {
 <a name="api_nan_new"></a>
 ### Local<T> NanNew<T>( ... )
 
-Use `NanNew` to construct almost all v8 objects and make new local handles.
-
-Note: Using NanNew with an std::string is possible, however, you should ensure
-to use the overload version (`NanNew(stdString)`) rather than the template
-version (`NanNew<v8::String>(stdString)`) as there is an unnecessary
-performance penalty to using the template version because of the inability for
-compilers to appropriately deduce to reference types on template specialization. 
+Use `NanNew` to construct almost all v8 objects (bound `Script`s are constructed with <a href="#api_nan_compile_script">`NanCompileScript(Handle)`</a>) and make new local handles.
 
 ```c++
 Local<String> s = NanNew<String>("value");
@@ -495,6 +552,15 @@ NAN_METHOD(Foo::Bar) {
 
 No `return` statement required.
 
+For convenience, `NanReturnValue` also accepts common primitives directly by implicitly performing an overloaded `NanNew(T)`.
+
+```c++
+NanReturnValue("FooBar!");
+NanReturnValue(true);
+NanReturnValue(12);
+NanReturnValue(3.14);
+```
+
 <a name="api_nan_return_undefined"></a>
 ### NanReturnUndefined()
 
@@ -534,6 +600,32 @@ NAN_METHOD(Foo::Baz) {
 }
 ```
 
+<a name="api_nan_return_this"></a>
+### NanReturnThis()
+
+Use `NanReturnThis` when you want to return `This` from your V8 accessible method:
+
+```c++
+NAN_METHOD(Foo::Baz) {
+  ...
+
+  NanReturnThis();
+}
+```
+
+<a name="api_nan_return_holder"></a>
+### NanReturnHolder()
+
+Use `NanReturnHolder` when you want to return `Holder` from your V8 accessible method:
+
+```c++
+NAN_METHOD(Foo::Baz) {
+  ...
+
+  NanReturnHolder();
+}
+```
+
 <a name="api_nan_scope"></a>
 ### NanScope()
 
@@ -625,7 +717,7 @@ NanSetInternalFieldPointer(wrapper, 0, this);
 ```
 
 <a name="api_nan_object_wrap_handle"></a>
-### Local<Object> NanObjectWrapHandle(Object)
+### Local<Object> NanObjectWrapHandle(const node::ObjectWrap &obj)
 
 When you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`:
 
@@ -634,10 +726,10 @@ NanObjectWrapHandle(iterator)->Get(NanNew<String>("end"))
 ```
 
 <a name="api_nan_symbol"></a>
-### <del>Local<String> NanSymbol(const char *)</del>
+### ~~Local<String> NanSymbol(const char *)~~
 
 Deprecated. Use `NanNew<String>` instead.
-<del>Use to create string symbol objects (i.e. `v8::String::NewSymbol(x)`), for getting and setting object properties, or names of objects.</del>
+~~Use to create string symbol objects (i.e. `v8::String::NewSymbol(x)`), for getting and setting object properties, or names of objects.~~
 
 ```c++
 bool foo = false;
@@ -678,12 +770,12 @@ const char *plugh(size_t *outputsize) {
 ```
 
 <a name="api_nan_raw_string"></a>
-### <del>void* NanRawString(Handle<Value>, enum Nan::Encoding, size_t *, void *, size_t, int)</del>
+### ~~void* NanRawString(Handle<Value>, enum Nan::Encoding, size_t *, void *, size_t, int)~~
 
 Deprecated. Use something else.
 
-<del>When you want to convert a V8 `String` to a `char*` buffer, use `NanRawString`. You have to supply an encoding as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows setting `String::WriteOptions`.
-Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer:</del>
+~~When you want to convert a V8 `String` to a `char*` buffer, use `NanRawString`. You have to supply an encoding as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows setting `String::WriteOptions`.
+Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer:~~
 
 ```c++
 size_t count;
@@ -693,12 +785,12 @@ delete[] reinterpret_cast<char*>(decoded);
 ```
 
 <a name="api_nan_c_string"></a>
-### <del>char* NanCString(Handle<Value>, size_t *[, char *, size_t, int])</del>
+### ~~char* NanCString(Handle<Value>, size_t *[, char *, size_t, int])~~
 
-Deprecated. Use `NanUtf8String` instead.
+Deprecated. Use `String::Utf8Value` or `NanUtf8String` instead.
 
-<del>When you want to convert a V8 `String` to a null-terminated C `char*` use `NanCString`. The resulting `char*` will be UTF-8-encoded, and you need to supply a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `v8::String::NO_OPTIONS`.
-Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer:</del>
+~~When you want to convert a V8 `String` to a null-terminated C `char*` use `NanCString`. The resulting `char*` will be UTF-8-encoded, and you need to supply a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `v8::String::NO_OPTIONS`.
+Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer:~~
 
 ```c++
 size_t count;
@@ -710,7 +802,8 @@ delete[] name;
 <a name="api_nan_ascii_string"></a>
 ### NanAsciiString
 
-Convert a `String` to zero-terminated, Ascii-encoded `char *`.
+Contrary to the name, this is not actually an ASCII string, it is a one-byte string with no particular encoding. Do not use unless you actually need this incorrect legacy behavior. Consider fixing your broken code instead. If you actually have a proper ASCII-string, use UTF-8, which is a proper superset of ASCII.
+Convert a `String` to zero-terminated, sort-of Ascii-encoded `char *`. The underlying buffer is freed when the owner object goes out of scope, so make a copy or heap allocation if you need it to stick around.
 
 ```c++
 NAN_METHOD(foo) {
@@ -719,10 +812,44 @@ NAN_METHOD(foo) {
 }
 ```
 
+####*WRONG*:
+the buffer `str` points to has been freed when `baz` was destroyed:
+```c++
+static char *str;
+
+NAN_METHOD(bar) {
+  NanScope();
+  NanAsciiString baz(arg[0]);
+
+  str = *baz;
+  NanReturnUndefined(); // baz goes out of scope, freeing str
+}
+
+...
+
+printf(str); // use-after-free error
+```
+
+####*RIGHT*:
+```c++
+static NanAsciiString *str;
+
+NAN_METHOD(bar) {
+  NanScope();
+  str = new NanAsciiString(arg[0]);
+  NanReturnUndefined();
+}
+
+...
+
+printf(**str);
+```
+
 <a name="api_nan_utf8_string"></a>
 ### NanUtf8String
 
-Convert a `String` to zero-terminated, Utf8-encoded `char *`.
+Equivalent to `String::Utf8Value`, it only exists for the sake of completeness.
+Convert a `String` to zero-terminated, Utf8-encoded `char *`. The underlying buffer is freed when the owner object goes out of scope, so make a copy or heap allocation if you need it to stick around.
 
 ```c++
 NAN_METHOD(foo) {
@@ -731,10 +858,45 @@ NAN_METHOD(foo) {
 }
 ```
 
+####*WRONG*:
+the buffer `str` points to has been freed when `baz` was destroyed:
+```c++
+static char *str;
+
+NAN_METHOD(bar) {
+  NanScope();
+  NanUtf8String baz(arg[0]);
+
+  str = *baz;
+  NanReturnUndefined(); // baz goes out of scope, freeing str
+}
+
+...
+
+printf(str); // use-after-free error
+```
+
+####*RIGHT*:
+```c++
+static NanUtf8String *str;
+
+NAN_METHOD(bar) {
+  NanScope();
+  str = new NanUtf8String(arg[0]);
+  NanReturnUndefined();
+}
+
+...
+
+printf(**str);
+```
+
+
 <a name="api_nan_ucs2_string"></a>
 ### NanUcs2String
 
-Convert a `String` to zero-terminated, Ucs2-encoded `uint16_t *`.
+Equivalent to `String::Value`, it only exists for the sake of completeness.
+Convert a `String` to zero-terminated, Ucs2-encoded `uint16_t *`. The underlying buffer is freed when the owner object goes out of scope, so make a copy or heap allocation if you need it to stick around.
 
 ```c++
 NAN_METHOD(foo) {
@@ -743,6 +905,39 @@ NAN_METHOD(foo) {
 }
 ```
 
+####*WRONG*:
+the buffer `str` points to has been freed when `baz` was destroyed:
+```c++
+static char *str;
+
+NAN_METHOD(bar) {
+  NanScope();
+  NanUcs2String baz(arg[0]);
+
+  str = *baz;
+  NanReturnUndefined(); // baz goes out of scope, freeing str
+}
+
+...
+
+printf(str); // use-after-free error
+```
+
+####*RIGHT*:
+```c++
+static NanUcs2String *str;
+
+NAN_METHOD(bar) {
+  NanScope();
+  str = new NanUcs2String(arg[0]);
+  NanReturnUndefined();
+}
+
+...
+
+printf(**str);
+```
+
 <a name="api_nan_boolean_option_value"></a>
 ### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool])
 
@@ -819,8 +1014,11 @@ careless use can lead to "double free or corruption" and other cryptic failures.
 Can be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent<FunctionTemplate>` handle for.
 
 <a name="api_nan_new_context_handle"></a>
-### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>])
-Creates a new `Local<Context>` handle.
+### ~~Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>])~~
+
+Deprecated. Use `NanNew<Context>` instead.
+
+~~Creates a new `Local<Context>` handle.~~
 
 ```c++
 Local<FunctionTemplate> ftmpl = NanNew<FunctionTemplate>();
@@ -901,7 +1099,22 @@ Use to add instance properties on function templates.
 <a name="api_nan_make_callback"></a>
 ### NanMakeCallback(target, func, argc, argv)
 
-Use instead of `node::MakeCallback` to call javascript functions. This is the only proper way of calling functions.
+Use instead of `node::MakeCallback` to call javascript functions. This (or `NanCallback`) is the only proper way of calling functions. You must _*never, ever*_ directly use `Function::Call`, it will lead to run-time failures.
+
+<a name="api_nan_encode"></a>
+### NanEncode(const void*, size_t[, enum Nan::Encoding])
+
+Replaces `node::Encode`.
+
+<a name="api_nan_decode_bytes"></a>
+### NanDecodeBytes(v8::Handle<v8::Value>[, enum Nan::Encoding])
+
+Replaces `node::DecodeBytes`.
+
+<a name="api_nan_decode_write"></a>
+### NanDecodeWrite(char *, size_t, v8::Handle<v8::Value>[, enum Nan::Encoding])
+
+Replaces `node::DecodeWrite`.
 
 <a name="api_nan_compile_script"></a>
 ### NanCompileScript(Handle<String> s [, const ScriptOrigin& origin])
@@ -943,6 +1156,36 @@ Simply does `RemoveGCPrologueCallback`
 
 Simply does `GetHeapStatistics`
 
+<a name="api_nan_set_counter_function"></a>
+### NanSetCounterFunction(CounterLookupCallback cb)
+
+Simply does `SetCounterFunction`
+
+<a name="api_nan_set_create_histogram_function"></a>
+### NanSetCreateHistogramFunction(CreateHistogramCallback cb)
+
+Simply does `SetCreateHistogramFunction`
+
+<a name="api_nan_set_add_histogram_sample_function"></a>
+### NanSetAddHistogramSampleFunction(AddHistogramSampleCallback cb)
+
+Simply does `SetAddHistogramSampleFunction`
+
+<a name="api_nan_idle_notification"></a>
+### NanIdleNotification(int idle_time_in_ms)
+
+Simply does `IdleNotification`
+
+<a name="api_nan_low_memory_notification"></a>
+### NanLowMemoryNotification()
+
+Simply does `LowMemoryNotification`
+
+<a name="api_nan_context_disposed_notification"></a>
+### NanContextDisposedNotification()
+
+Simply does `ContextDisposedNotification`
+
 <a name="api_nan_callback"></a>
 ### NanCallback
 
@@ -975,7 +1218,7 @@ Handle<Value> argv[] = {
 callback->Call(2, argv);
 ```
 
-`NanCallback` also has a `Local<Function> GetCallback()` method that you can use
+`NanCallback` also has a `Local<Function> GetFunction()` method that you can use
 to fetch a local handle to the underlying callback function, as well  as a
 `void SetFunction(Handle<Function>)` for setting the callback on the
 `NanCallback`. You can check if a `NanCallback` is empty with the `bool IsEmpty()` method. Additionally a generic constructor is available for using
@@ -1033,9 +1276,114 @@ protected:
 
 `NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`.
 
-### Contributors
+<a name="api"></a>
+### Tests
+
+To run the NAN tests do:
+
+``` sh
+npm install
+npm run-script rebuild-tests
+npm test
+```
+
+Or just:
+
+``` sh
+npm install
+make test
+```
+
+## Porting
+
+Follows is a guide to porting your C++ node to NAN.
+
+<table><tbody>
+
+<tr><th>Aspect</th><th>Without NAN</th><th>With NAN</th></tr>
+
+<tr><td>Function declaration</td><td><pre>class MyClass : public ObjectWrap {
+    ....
+    static Handle<Value> ToString(const Arguments& args);
+    ....
+}</pre></td></th><td><pre>class MyClass : public ObjectWrap {
+    ....
+    static NAN_METHOD(ToString);
+    ....
+}</pre></td></tr>
+
+<tr><td>Function definition</td><td><pre>Handle<Value>
+MyClass::ToString(const Arguments& args)
+{
+	HandleScope scope;
+	....
+}</pre></td></th><td><pre>
+NAN_METHOD(MyClass::ToString)
+{
+  NanScope();
+  ....
+}</pre></td></tr>
+
+<tr><td>Return a value</td><td><pre>return scope.Close(result);</pre></td></th><td><pre>NanReturnValue(result);</pre></td></tr>
+
+<tr><td>Return undefined</td><td><pre>return Undefined();</pre></td></th><td><pre>NanReturnUndefined();</pre></td></tr>
+
+<tr><td>Throw an error</td><td><pre>return ThrowException(
+  Exception::Error(
+    String::New("Error text...")));</pre></td></th><td><pre>return NanThrowError("Error text...");</pre></td></tr>
+
+<tr><td>New v8 string literal</td><td><pre>String::NewSymbol("my text")</pre></td></th><td><pre>NanNew("my text")</pre></td></tr>
+
+</tbody></table>
+
+## Contributors
+
+<a name="governance"></a>
+
+## Governance & Contributing
+
+NAN is governed by the [io.js](https://iojs.org/) Addon API Working Group
+
+### Addon API Working Group (WG)
+
+The NAN project is jointly governed by a Working Group which is responsible for high-level guidance of the project.
+
+Members of the WG are also known as Collaborators, there is no distinction between the two, unlike other io.js projects.
+
+The WG has final authority over this project including:
+
+* Technical direction
+* Project governance and process (including this policy)
+* Contribution policy
+* GitHub repository hosting
+* Maintaining the list of additional Collaborators
+
+For the current list of WG members, see the project [README.md](./README.md#collaborators).
+
+Individuals making significant and valuable contributions are made members of the WG and given commit-access to the project. These individuals are identified by the WG and their addition to the WG is discussed via GitHub and requires unanimous consensus amongst those WG members participating in the discussion with a quorum of 50% of WG members required for acceptance of the vote.
+
+_Note:_ If you make a significant contribution and are not considered for commit-access log an issue or contact a WG member directly.
+
+For the current list of WG members / Collaborators, see the project [README.md](./README.md#collaborators).
+
+### Consensus Seeking Process
+
+The WG follows a [Consensus Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making) decision making model.
+
+Modifications of the contents of the NAN repository are made on a collaborative basis. Anybody with a GitHub account may propose a modification via pull request and it will be considered by the WG. All pull requests must be reviewed and accepted by a WG member with sufficient expertise who is able to take full responsibility for the change. In the case of pull requests proposed by an existing WG member, an additional WG member is required for sign-off. Consensus should be sought if addit [...]
+
+If a change proposal cannot reach a consensus, a WG member can call for a vote amongst the members of the WG. Simple majority wins.
+
+### Developer's Certificate of Origin 1.0
+
+By making a contribution to this project, I certify that:
+
+* (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or
+* (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or
+* (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
 
-NAN is only possible due to the excellent work of the following contributors:
+<a name="collaborators"></a>
+### WG Members / Collaborators
 
 <table><tbody>
 <tr><th align="left">Rod Vagg</th><td><a href="https://github.com/rvagg">GitHub/rvagg</a></td><td><a href="http://twitter.com/rvagg">Twitter/@rvagg</a></td></tr>
@@ -1044,11 +1392,11 @@ NAN is only possible due to the excellent work of the following contributors:
 <tr><th align="left">Nathan Rajlich</th><td><a href="https://github.com/TooTallNate">GitHub/TooTallNate</a></td><td><a href="http://twitter.com/TooTallNate">Twitter/@TooTallNate</a></td></tr>
 <tr><th align="left">Brett Lawson</th><td><a href="https://github.com/brett19">GitHub/brett19</a></td><td><a href="http://twitter.com/brett19x">Twitter/@brett19x</a></td></tr>
 <tr><th align="left">Ben Noordhuis</th><td><a href="https://github.com/bnoordhuis">GitHub/bnoordhuis</a></td><td><a href="http://twitter.com/bnoordhuis">Twitter/@bnoordhuis</a></td></tr>
+<tr><th align="left">David Siegel</th><td><a href="https://github.com/agnat">GitHub/agnat</a></td><td>-</td></tr>
 </tbody></table>
 
-Licence & copyright
------------------------
+## Licence & copyright
 
-Copyright (c) 2014 NAN contributors (listed above).
+Copyright (c) 2015 NAN WG Members / Collaborators (listed above).
 
-Native Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
+Native Abstractions for Node.js is licensed under an MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
diff --git a/appveyor.yml b/appveyor.yml
index 657eed6..3429453 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,32 +1,38 @@
 # http://www.appveyor.com/docs/appveyor-yml
 
-# Test against these versions of Node.js.
+# Test against these versions of Io.js and Node.js.
 environment:
   matrix:
+  # node.js
     - nodejs_version: "0.8"
     - nodejs_version: "0.10"
-    - nodejs_version: "0.11"
+    - nodejs_version: "0.12"
+  # io.js
+    - nodejs_version: "1"
 
 # Install scripts. (runs after repo cloning)
 install:
   # Get the latest stable version of Node 0.STABLE.latest
-  - npm install npm
-  - move node_modules npm
-  - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version)
+  - ps: if($env:nodejs_version -eq "0.8") {Install-Product node $env:nodejs_version}
+  - ps: if($env:nodejs_version -ne "0.8") {Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version)}
+  - IF NOT %nodejs_version% == 1 npm -g install npm
+  - IF NOT %nodejs_version% == 1 set PATH=%APPDATA%\npm;%PATH%
   # Typical npm stuff.
-  - npm/.bin/npm install
-  - npm/.bin/npm run rebuild-tests
+  - npm install
+  - IF %nodejs_version% == 0.8 node node_modules\node-gyp\bin\node-gyp.js rebuild --directory test
+  - IF NOT %nodejs_version% == 0.8 npm run rebuild-tests
 
 # Post-install test scripts.
 test_script:
   # Output useful info for debugging.
   - node --version
   - npm --version
-  - cmd: npm test
+  # run tests
+  - IF NOT %nodejs_version% == 1 npm test
+  - IF %nodejs_version% == 1 iojs node_modules\tap\bin\tap.js --gc test\js\*-test.js
 
 # Don't actually build.
 build: off
 
 # Set build version format here instead of in the admin panel.
 version: "{build}"
-
diff --git a/cpplint.py b/cpplint.py
index 76d0735..ccc25d4 100644
--- a/cpplint.py
+++ b/cpplint.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 #
 # Copyright (c) 2009 Google Inc. All rights reserved.
 #
@@ -114,7 +114,7 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
       ignored.
 
       Examples:
-        Assuing that src/.git exists, the header guard CPP variables for
+        Assuming that src/.git exists, the header guard CPP variables for
         src/chrome/browser/ui/browser.h are:
 
         No flag => CHROME_BROWSER_UI_BROWSER_H_
@@ -133,6 +133,41 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
 
       Examples:
         --extensions=hpp,cpp
+
+    cpplint.py supports per-directory configurations specified in CPPLINT.cfg
+    files. CPPLINT.cfg file can contain a number of key=value pairs.
+    Currently the following options are supported:
+
+      set noparent
+      filter=+filter1,-filter2,...
+      exclude_files=regex
+      linelength=80
+
+    "set noparent" option prevents cpplint from traversing directory tree
+    upwards looking for more .cfg files in parent directories. This option
+    is usually placed in the top-level project directory.
+
+    The "filter" option is similar in function to --filter flag. It specifies
+    message filters in addition to the |_DEFAULT_FILTERS| and those specified
+    through --filter command-line flag.
+
+    "exclude_files" allows to specify a regular expression to be matched against
+    a file name. If the expression matches, the file is skipped and not run
+    through liner.
+
+    "linelength" allows to specify the allowed line length for the project.
+
+    CPPLINT.cfg has an effect on files in the same directory and all
+    sub-directories, unless overridden by a nested configuration file.
+
+      Example file:
+        filter=-build/include_order,+build/include_alpha
+        exclude_files=.*\.cc
+
+    The above example disables build/include_order warning and enables
+    build/include_alpha as well as excludes all .cc from being
+    processed by linter, in the current directory (where the .cfg
+    file is located) and all sub-directories.
 """
 
 # We categorize each error message we print.  Here are the categories.
@@ -140,70 +175,79 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
 # If you add a new error message with a new category, add it to the list
 # here!  cpplint_unittest.py should tell you if you forget to do this.
 _ERROR_CATEGORIES = [
-  'build/class',
-  'build/deprecated',
-  'build/endif_comment',
-  'build/explicit_make_pair',
-  'build/forward_decl',
-  'build/header_guard',
-  'build/include',
-  'build/include_alpha',
-  'build/include_order',
-  'build/include_what_you_use',
-  'build/namespaces',
-  'build/printf_format',
-  'build/storage_class',
-  'legal/copyright',
-  'readability/alt_tokens',
-  'readability/braces',
-  'readability/casting',
-  'readability/check',
-  'readability/constructors',
-  'readability/fn_size',
-  'readability/function',
-  'readability/multiline_comment',
-  'readability/multiline_string',
-  'readability/namespace',
-  'readability/nolint',
-  'readability/nul',
-  'readability/streams',
-  'readability/todo',
-  'readability/utf8',
-  'runtime/arrays',
-  'runtime/casting',
-  'runtime/explicit',
-  'runtime/int',
-  'runtime/init',
-  'runtime/invalid_increment',
-  'runtime/member_string_references',
-  'runtime/memset',
-  'runtime/operator',
-  'runtime/printf',
-  'runtime/printf_format',
-  'runtime/references',
-  'runtime/string',
-  'runtime/threadsafe_fn',
-  'runtime/vlog',
-  'whitespace/blank_line',
-  'whitespace/braces',
-  'whitespace/comma',
-  'whitespace/comments',
-  'whitespace/empty_conditional_body',
-  'whitespace/empty_loop_body',
-  'whitespace/end_of_line',
-  'whitespace/ending_newline',
-  'whitespace/forcolon',
-  'whitespace/indent',
-  'whitespace/line_length',
-  'whitespace/newline',
-  'whitespace/operators',
-  'whitespace/parens',
-  'whitespace/semicolon',
-  'whitespace/tab',
-  'whitespace/todo'
-  ]
-
-# The default state of the category filter. This is overrided by the --filter=
+    'build/class',
+    'build/c++11',
+    'build/deprecated',
+    'build/endif_comment',
+    'build/explicit_make_pair',
+    'build/forward_decl',
+    'build/header_guard',
+    'build/include',
+    'build/include_alpha',
+    'build/include_order',
+    'build/include_what_you_use',
+    'build/namespaces',
+    'build/printf_format',
+    'build/storage_class',
+    'legal/copyright',
+    'readability/alt_tokens',
+    'readability/braces',
+    'readability/casting',
+    'readability/check',
+    'readability/constructors',
+    'readability/fn_size',
+    'readability/function',
+    'readability/inheritance',
+    'readability/multiline_comment',
+    'readability/multiline_string',
+    'readability/namespace',
+    'readability/nolint',
+    'readability/nul',
+    'readability/strings',
+    'readability/todo',
+    'readability/utf8',
+    'runtime/arrays',
+    'runtime/casting',
+    'runtime/explicit',
+    'runtime/int',
+    'runtime/init',
+    'runtime/invalid_increment',
+    'runtime/member_string_references',
+    'runtime/memset',
+    'runtime/indentation_namespace',
+    'runtime/operator',
+    'runtime/printf',
+    'runtime/printf_format',
+    'runtime/references',
+    'runtime/string',
+    'runtime/threadsafe_fn',
+    'runtime/vlog',
+    'whitespace/blank_line',
+    'whitespace/braces',
+    'whitespace/comma',
+    'whitespace/comments',
+    'whitespace/empty_conditional_body',
+    'whitespace/empty_loop_body',
+    'whitespace/end_of_line',
+    'whitespace/ending_newline',
+    'whitespace/forcolon',
+    'whitespace/indent',
+    'whitespace/line_length',
+    'whitespace/newline',
+    'whitespace/operators',
+    'whitespace/parens',
+    'whitespace/semicolon',
+    'whitespace/tab',
+    'whitespace/todo',
+    ]
+
+# These error categories are no longer enforced by cpplint, but for backwards-
+# compatibility they may still appear in NOLINT comments.
+_LEGACY_ERROR_CATEGORIES = [
+    'readability/streams',
+    ]
+
+# The default state of the category filter. This is overridden by the --filter=
 # flag. By default all errors are on, so only add here categories that should be
 # off by default (i.e., categories that must be enabled by the --filter= flags).
 # All entries here should start with a '-' or '+', as in the --filter= flag.
@@ -213,7 +257,6 @@ _DEFAULT_FILTERS = ['-build/include_alpha']
 # decided those were OK, as long as they were in UTF-8 and didn't represent
 # hard-coded international strings, which belong in a separate i18n file.
 
-
 # C++ headers
 _CPP_HEADERS = frozenset([
     # Legacy
@@ -350,6 +393,16 @@ _CPP_HEADERS = frozenset([
     'cwctype',
     ])
 
+
+# These headers are excluded from [build/include] and [build/include_order]
+# checks:
+# - Anything not following google file name conventions (containing an
+#   uppercase character, such as Python.h or nsStringAPI.h, for example).
+# - Lua headers.
+_THIRD_PARTY_HEADERS_PATTERN = re.compile(
+    r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
+
+
 # Assertion macros.  These are defined in base/logging.h and
 # testing/base/gunit.h.  Note that the _M versions need to come first
 # for substring matching to work.
@@ -432,9 +485,6 @@ _MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
 
 _regexp_compile_cache = {}
 
-# Finds occurrences of NOLINT or NOLINT(...).
-_RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?')
-
 # {str, set(int)}: a map from error categories to sets of linenumbers
 # on which those errors are expected and should be suppressed.
 _error_suppressions = {}
@@ -464,24 +514,27 @@ def ParseNolintSuppressions(filename, raw_line, linenum, error):
     linenum: int, the number of the current line.
     error: function, an error handler.
   """
-  # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*).
-  matched = _RE_SUPPRESSION.search(raw_line)
+  matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
   if matched:
-    category = matched.group(1)
+    if matched.group(1):
+      suppressed_line = linenum + 1
+    else:
+      suppressed_line = linenum
+    category = matched.group(2)
     if category in (None, '(*)'):  # => "suppress all"
-      _error_suppressions.setdefault(None, set()).add(linenum)
+      _error_suppressions.setdefault(None, set()).add(suppressed_line)
     else:
       if category.startswith('(') and category.endswith(')'):
         category = category[1:-1]
         if category in _ERROR_CATEGORIES:
-          _error_suppressions.setdefault(category, set()).add(linenum)
-        else:
+          _error_suppressions.setdefault(category, set()).add(suppressed_line)
+        elif category not in _LEGACY_ERROR_CATEGORIES:
           error(filename, linenum, 'readability/nolint', 5,
                 'Unknown NOLINT error category: %s' % category)
 
 
 def ResetNolintSuppressions():
-  "Resets the set of NOLINT suppressions to empty."
+  """Resets the set of NOLINT suppressions to empty."""
   _error_suppressions.clear()
 
 
@@ -500,6 +553,7 @@ def IsErrorSuppressedByNolint(category, linenum):
   return (linenum in _error_suppressions.get(category, set()) or
           linenum in _error_suppressions.get(None, set()))
 
+
 def Match(pattern, s):
   """Matches the string with the pattern, caching the compiled regexp."""
   # The regexp compilation caching is inlined in both Match and Search for
@@ -535,11 +589,12 @@ def Search(pattern, s):
   return _regexp_compile_cache[pattern].search(s)
 
 
-class _IncludeState(dict):
+class _IncludeState(object):
   """Tracks line numbers for includes, and the order in which includes appear.
 
-  As a dict, an _IncludeState object serves as a mapping between include
-  filename and line number on which that file was included.
+  include_list contains list of lists of (header, line number) pairs.
+  It's a lists of lists rather than just one flat list to make it
+  easier to update across preprocessor boundaries.
 
   Call CheckNextIncludeOrder() once for each header in the file, passing
   in the type constants defined above. Calls in an illegal order will
@@ -570,15 +625,42 @@ class _IncludeState(dict):
       }
 
   def __init__(self):
-    dict.__init__(self)
-    self.ResetSection()
+    self.include_list = [[]]
+    self.ResetSection('')
+
+  def FindHeader(self, header):
+    """Check if a header has already been included.
+
+    Args:
+      header: header to check.
+    Returns:
+      Line number of previous occurrence, or -1 if the header has not
+      been seen before.
+    """
+    for section_list in self.include_list:
+      for f in section_list:
+        if f[0] == header:
+          return f[1]
+    return -1
 
-  def ResetSection(self):
+  def ResetSection(self, directive):
+    """Reset section checking for preprocessor directive.
+
+    Args:
+      directive: preprocessor directive (e.g. "if", "else").
+    """
     # The name of the current section.
     self._section = self._INITIAL_SECTION
     # The path of last found header.
     self._last_header = ''
 
+    # Update list of includes.  Note that we never pop from the
+    # include list.
+    if directive in ('if', 'ifdef', 'ifndef'):
+      self.include_list.append([])
+    elif directive in ('else', 'elif'):
+      self.include_list[-1] = []
+
   def SetLastHeader(self, header_path):
     self._last_header = header_path
 
@@ -614,7 +696,7 @@ class _IncludeState(dict):
     # If previous line was a blank line, assume that the headers are
     # intentionally sorted the way they are.
     if (self._last_header > header_path and
-        not Match(r'^\s*$', clean_lines.elided[linenum - 1])):
+        Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
       return False
     return True
 
@@ -680,6 +762,8 @@ class _CppLintState(object):
     self.error_count = 0    # global count of reported errors
     # filters to apply when emitting error messages
     self.filters = _DEFAULT_FILTERS[:]
+    # backup of filter list. Used to restore the state after each file.
+    self._filters_backup = self.filters[:]
     self.counting = 'total'  # In what way are we counting errors?
     self.errors_by_category = {}  # string to int dict storing error counts
 
@@ -718,6 +802,10 @@ class _CppLintState(object):
     """
     # Default filters always have less priority than the flag ones.
     self.filters = _DEFAULT_FILTERS[:]
+    self.AddFilters(filters)
+
+  def AddFilters(self, filters):
+    """ Adds more filters to the existing list of error-message filters. """
     for filt in filters.split(','):
       clean_filt = filt.strip()
       if clean_filt:
@@ -727,6 +815,14 @@ class _CppLintState(object):
         raise ValueError('Every filter in --filters must start with + or -'
                          ' (%s does not)' % filt)
 
+  def BackupFilters(self):
+    """ Saves the current filter list to backup storage."""
+    self._filters_backup = self.filters[:]
+
+  def RestoreFilters(self):
+    """ Restores filters previously backed up."""
+    self.filters = self._filters_backup[:]
+
   def ResetErrorCounts(self):
     """Sets the module's error statistic back to zero."""
     self.error_count = 0
@@ -794,6 +890,25 @@ def _SetFilters(filters):
   """
   _cpplint_state.SetFilters(filters)
 
+def _AddFilters(filters):
+  """Adds more filter overrides.
+
+  Unlike _SetFilters, this function does not reset the current list of filters
+  available.
+
+  Args:
+    filters: A string of comma-separated filters (eg "whitespace/indent").
+             Each filter should start with + or -; else we die.
+  """
+  _cpplint_state.AddFilters(filters)
+
+def _BackupFilters():
+  """ Saves the current filter list to backup storage."""
+  _cpplint_state.BackupFilters()
+
+def _RestoreFilters():
+  """ Restores filters previously backed up."""
+  _cpplint_state.RestoreFilters()
 
 class _FunctionState(object):
   """Tracks current function name and the number of lines in its body."""
@@ -856,7 +971,7 @@ class _IncludeError(Exception):
   pass
 
 
-class FileInfo:
+class FileInfo(object):
   """Provides utility functions for filenames.
 
   FileInfo provides easy access to the components of a file's path
@@ -954,6 +1069,7 @@ def _ShouldPrintError(category, confidence, linenum):
   # the verbosity level isn't high enough, or the filters filter it out.
   if IsErrorSuppressedByNolint(category, linenum):
     return False
+
   if confidence < _cpplint_state.verbose_level:
     return False
 
@@ -1011,11 +1127,9 @@ def Error(filename, linenum, category, confidence, message):
 # Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
     r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
-# Matches strings.  Escape codes should already be removed by ESCAPES.
-_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"')
-# Matches characters.  Escape codes should already be removed by ESCAPES.
-_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'")
-# Matches multi-line C++ comments.
+# Match a single C style comment on the same line.
+_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/'
+# Matches multi-line C style comments.
 # This RE is a little bit more complicated than one might expect, because we
 # have to take care of space removals tools so we can handle comments inside
 # statements better.
@@ -1024,10 +1138,10 @@ _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'")
 # if this doesn't work we try on left side but only if there's a non-character
 # on the right.
 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
-    r"""(\s*/\*.*\*/\s*$|
-            /\*.*\*/\s+|
-         \s+/\*.*\*/(?=\W)|
-            /\*.*\*/)""", re.VERBOSE)
+    r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' +
+    _RE_PATTERN_C_COMMENTS + r'\s+|' +
+    r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' +
+    _RE_PATTERN_C_COMMENTS + r')')
 
 
 def IsCppString(line):
@@ -1082,9 +1196,12 @@ def CleanseRawStrings(raw_lines):
         delimiter = None
       else:
         # Haven't found the end yet, append a blank line.
-        line = ''
+        line = '""'
 
-    else:
+    # Look for beginning of a raw string, and replace them with
+    # empty strings.  This is done in a loop to handle multiple raw
+    # strings on the same line.
+    while delimiter is None:
       # Look for beginning of a raw string.
       # See 2.14.15 [lex.string] for syntax.
       matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
@@ -1100,6 +1217,8 @@ def CleanseRawStrings(raw_lines):
         else:
           # Start of a multi-line raw string
           line = matched.group(1) + '""'
+      else:
+        break
 
     lines_without_raw_strings.append(line)
 
@@ -1133,7 +1252,7 @@ def RemoveMultiLineCommentsFromRange(lines, begin, end):
   # Having // dummy comments makes the lines non-empty, so we will not get
   # unnecessary blank line warnings later in the code.
   for i in range(begin, end):
-    lines[i] = '// dummy'
+    lines[i] = '/**/'
 
 
 def RemoveMultiLineComments(filename, lines, error):
@@ -1169,12 +1288,14 @@ def CleanseComments(line):
 
 
 class CleansedLines(object):
-  """Holds 3 copies of all lines with different preprocessing applied to them.
+  """Holds 4 copies of all lines with different preprocessing applied to them.
 
-  1) elided member contains lines without strings and comments,
-  2) lines member contains lines without comments, and
+  1) elided member contains lines without strings and comments.
+  2) lines member contains lines without comments.
   3) raw_lines member contains all the lines without processing.
-  All these three members are of <type 'list'>, and of the same length.
+  4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
+     strings removed.
+  All these members are of <type 'list'>, and of the same length.
   """
 
   def __init__(self, lines):
@@ -1205,38 +1326,138 @@ class CleansedLines(object):
     Returns:
       The line with collapsed strings.
     """
-    if not _RE_PATTERN_INCLUDE.match(elided):
-      # Remove escaped characters first to make quote/single quote collapsing
-      # basic.  Things that look like escaped characters shouldn't occur
-      # outside of strings and chars.
-      elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
-      elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided)
-      elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided)
-    return elided
+    if _RE_PATTERN_INCLUDE.match(elided):
+      return elided
+
+    # Remove escaped characters first to make quote/single quote collapsing
+    # basic.  Things that look like escaped characters shouldn't occur
+    # outside of strings and chars.
+    elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
+
+    # Replace quoted strings and digit separators.  Both single quotes
+    # and double quotes are processed in the same loop, otherwise
+    # nested quotes wouldn't work.
+    collapsed = ''
+    while True:
+      # Find the first quote character
+      match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
+      if not match:
+        collapsed += elided
+        break
+      head, quote, tail = match.groups()
+
+      if quote == '"':
+        # Collapse double quoted strings
+        second_quote = tail.find('"')
+        if second_quote >= 0:
+          collapsed += head + '""'
+          elided = tail[second_quote + 1:]
+        else:
+          # Unmatched double quote, don't bother processing the rest
+          # of the line since this is probably a multiline string.
+          collapsed += elided
+          break
+      else:
+        # Found single quote, check nearby text to eliminate digit separators.
+        #
+        # There is no special handling for floating point here, because
+        # the integer/fractional/exponent parts would all be parsed
+        # correctly as long as there are digits on both sides of the
+        # separator.  So we are fine as long as we don't see something
+        # like "0.'3" (gcc 4.9.0 will not allow this literal).
+        if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
+          match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
+          collapsed += head + match_literal.group(1).replace("'", '')
+          elided = match_literal.group(2)
+        else:
+          second_quote = tail.find('\'')
+          if second_quote >= 0:
+            collapsed += head + "''"
+            elided = tail[second_quote + 1:]
+          else:
+            # Unmatched single quote
+            collapsed += elided
+            break
+
+    return collapsed
 
 
-def FindEndOfExpressionInLine(line, startpos, depth, startchar, endchar):
-  """Find the position just after the matching endchar.
+def FindEndOfExpressionInLine(line, startpos, stack):
+  """Find the position just after the end of current parenthesized expression.
 
   Args:
     line: a CleansedLines line.
     startpos: start searching at this position.
-    depth: nesting level at startpos.
-    startchar: expression opening character.
-    endchar: expression closing character.
+    stack: nesting stack at startpos.
 
   Returns:
-    On finding matching endchar: (index just after matching endchar, 0)
-    Otherwise: (-1, new depth at end of this line)
+    On finding matching end: (index just after matching end, None)
+    On finding an unclosed expression: (-1, None)
+    Otherwise: (-1, new stack at end of this line)
   """
   for i in xrange(startpos, len(line)):
-    if line[i] == startchar:
-      depth += 1
-    elif line[i] == endchar:
-      depth -= 1
-      if depth == 0:
-        return (i + 1, 0)
-  return (-1, depth)
+    char = line[i]
+    if char in '([{':
+      # Found start of parenthesized expression, push to expression stack
+      stack.append(char)
+    elif char == '<':
+      # Found potential start of template argument list
+      if i > 0 and line[i - 1] == '<':
+        # Left shift operator
+        if stack and stack[-1] == '<':
+          stack.pop()
+          if not stack:
+            return (-1, None)
+      elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
+        # operator<, don't add to stack
+        continue
+      else:
+        # Tentative start of template argument list
+        stack.append('<')
+    elif char in ')]}':
+      # Found end of parenthesized expression.
+      #
+      # If we are currently expecting a matching '>', the pending '<'
+      # must have been an operator.  Remove them from expression stack.
+      while stack and stack[-1] == '<':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+      if ((stack[-1] == '(' and char == ')') or
+          (stack[-1] == '[' and char == ']') or
+          (stack[-1] == '{' and char == '}')):
+        stack.pop()
+        if not stack:
+          return (i + 1, None)
+      else:
+        # Mismatched parentheses
+        return (-1, None)
+    elif char == '>':
+      # Found potential end of template argument list.
+
+      # Ignore "->" and operator functions
+      if (i > 0 and
+          (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
+        continue
+
+      # Pop the stack if there is a matching '<'.  Otherwise, ignore
+      # this '>' since it must be an operator.
+      if stack:
+        if stack[-1] == '<':
+          stack.pop()
+          if not stack:
+            return (i + 1, None)
+    elif char == ';':
+      # Found something that look like end of statements.  If we are currently
+      # expecting a '>', the matching '<' must have been an operator, since
+      # template argument list should not contain statements.
+      while stack and stack[-1] == '<':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+
+  # Did not find end of expression or unbalanced parentheses on this line
+  return (-1, stack)
 
 
 def CloseExpression(clean_lines, linenum, pos):
@@ -1245,6 +1466,11 @@ def CloseExpression(clean_lines, linenum, pos):
   If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
   linenum/pos that correspond to the closing of the expression.
 
+  TODO(unknown): cpplint spends a fair bit of time matching parentheses.
+  Ideally we would want to index all opening and closing parentheses once
+  and have CloseExpression be just a simple lookup, but due to preprocessor
+  tricks, this is not so easy.
+
   Args:
     clean_lines: A CleansedLines instance containing the file.
     linenum: The number of the line to check.
@@ -1258,35 +1484,28 @@ def CloseExpression(clean_lines, linenum, pos):
   """
 
   line = clean_lines.elided[linenum]
-  startchar = line[pos]
-  if startchar not in '({[<':
+  if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
     return (line, clean_lines.NumLines(), -1)
-  if startchar == '(': endchar = ')'
-  if startchar == '[': endchar = ']'
-  if startchar == '{': endchar = '}'
-  if startchar == '<': endchar = '>'
 
   # Check first line
-  (end_pos, num_open) = FindEndOfExpressionInLine(
-      line, pos, 0, startchar, endchar)
+  (end_pos, stack) = FindEndOfExpressionInLine(line, pos, [])
   if end_pos > -1:
     return (line, linenum, end_pos)
 
   # Continue scanning forward
-  while linenum < clean_lines.NumLines() - 1:
+  while stack and linenum < clean_lines.NumLines() - 1:
     linenum += 1
     line = clean_lines.elided[linenum]
-    (end_pos, num_open) = FindEndOfExpressionInLine(
-        line, 0, num_open, startchar, endchar)
+    (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack)
     if end_pos > -1:
       return (line, linenum, end_pos)
 
-  # Did not find endchar before end of file, give up
+  # Did not find end of expression before end of file, give up
   return (line, clean_lines.NumLines(), -1)
 
 
-def FindStartOfExpressionInLine(line, endpos, depth, startchar, endchar):
-  """Find position at the matching startchar.
+def FindStartOfExpressionInLine(line, endpos, stack):
+  """Find position at the matching start of current expression.
 
   This is almost the reverse of FindEndOfExpressionInLine, but note
   that the input position and returned position differs by 1.
@@ -1294,22 +1513,72 @@ def FindStartOfExpressionInLine(line, endpos, depth, startchar, endchar):
   Args:
     line: a CleansedLines line.
     endpos: start searching at this position.
-    depth: nesting level at endpos.
-    startchar: expression opening character.
-    endchar: expression closing character.
+    stack: nesting stack at endpos.
 
   Returns:
-    On finding matching startchar: (index at matching startchar, 0)
-    Otherwise: (-1, new depth at beginning of this line)
+    On finding matching start: (index at matching start, None)
+    On finding an unclosed expression: (-1, None)
+    Otherwise: (-1, new stack at beginning of this line)
   """
-  for i in xrange(endpos, -1, -1):
-    if line[i] == endchar:
-      depth += 1
-    elif line[i] == startchar:
-      depth -= 1
-      if depth == 0:
-        return (i, 0)
-  return (-1, depth)
+  i = endpos
+  while i >= 0:
+    char = line[i]
+    if char in ')]}':
+      # Found end of expression, push to expression stack
+      stack.append(char)
+    elif char == '>':
+      # Found potential end of template argument list.
+      #
+      # Ignore it if it's a "->" or ">=" or "operator>"
+      if (i > 0 and
+          (line[i - 1] == '-' or
+           Match(r'\s>=\s', line[i - 1:]) or
+           Search(r'\boperator\s*$', line[0:i]))):
+        i -= 1
+      else:
+        stack.append('>')
+    elif char == '<':
+      # Found potential start of template argument list
+      if i > 0 and line[i - 1] == '<':
+        # Left shift operator
+        i -= 1
+      else:
+        # If there is a matching '>', we can pop the expression stack.
+        # Otherwise, ignore this '<' since it must be an operator.
+        if stack and stack[-1] == '>':
+          stack.pop()
+          if not stack:
+            return (i, None)
+    elif char in '([{':
+      # Found start of expression.
+      #
+      # If there are any unmatched '>' on the stack, they must be
+      # operators.  Remove those.
+      while stack and stack[-1] == '>':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+      if ((char == '(' and stack[-1] == ')') or
+          (char == '[' and stack[-1] == ']') or
+          (char == '{' and stack[-1] == '}')):
+        stack.pop()
+        if not stack:
+          return (i, None)
+      else:
+        # Mismatched parentheses
+        return (-1, None)
+    elif char == ';':
+      # Found something that look like end of statements.  If we are currently
+      # expecting a '<', the matching '>' must have been an operator, since
+      # template argument list should not contain statements.
+      while stack and stack[-1] == '>':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+
+    i -= 1
+
+  return (-1, stack)
 
 
 def ReverseCloseExpression(clean_lines, linenum, pos):
@@ -1330,30 +1599,23 @@ def ReverseCloseExpression(clean_lines, linenum, pos):
     return is the 'cleansed' line at linenum.
   """
   line = clean_lines.elided[linenum]
-  endchar = line[pos]
-  if endchar not in ')}]>':
+  if line[pos] not in ')}]>':
     return (line, 0, -1)
-  if endchar == ')': startchar = '('
-  if endchar == ']': startchar = '['
-  if endchar == '}': startchar = '{'
-  if endchar == '>': startchar = '<'
 
   # Check last line
-  (start_pos, num_open) = FindStartOfExpressionInLine(
-      line, pos, 0, startchar, endchar)
+  (start_pos, stack) = FindStartOfExpressionInLine(line, pos, [])
   if start_pos > -1:
     return (line, linenum, start_pos)
 
   # Continue scanning backward
-  while linenum > 0:
+  while stack and linenum > 0:
     linenum -= 1
     line = clean_lines.elided[linenum]
-    (start_pos, num_open) = FindStartOfExpressionInLine(
-        line, len(line) - 1, num_open, startchar, endchar)
+    (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack)
     if start_pos > -1:
       return (line, linenum, start_pos)
 
-  # Did not find startchar before beginning of file, give up
+  # Did not find start of expression before beginning of file, give up
   return (line, 0, -1)
 
 
@@ -1370,6 +1632,22 @@ def CheckForCopyright(filename, lines, error):
           'You should have a line: "Copyright [year] <Copyright Owner>"')
 
 
+def GetIndentLevel(line):
+  """Return the number of leading spaces in line.
+
+  Args:
+    line: A string to check.
+
+  Returns:
+    An integer count of leading spaces, possibly zero.
+  """
+  indent = Match(r'^( *)\S', line)
+  if indent:
+    return len(indent.group(1))
+  else:
+    return 0
+
+
 def GetHeaderGuardCPPVariable(filename):
   """Returns the CPP variable that should be used as a header guard.
 
@@ -1386,15 +1664,17 @@ def GetHeaderGuardCPPVariable(filename):
   # flymake.
   filename = re.sub(r'_flymake\.h$', '.h', filename)
   filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
-
+  # Replace 'c++' with 'cpp'.
+  filename = filename.replace('C++', 'cpp').replace('c++', 'cpp')
+  
   fileinfo = FileInfo(filename)
   file_path_from_root = fileinfo.RepositoryName()
   if _root:
     file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root)
-  return re.sub(r'[-./\s]', '_', file_path_from_root).upper() + '_'
+  return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
 
 
-def CheckForHeaderGuard(filename, lines, error):
+def CheckForHeaderGuard(filename, clean_lines, error):
   """Checks that the file contains a header guard.
 
   Logs an error if no #ifndef header guard is present.  For other
@@ -1402,18 +1682,29 @@ def CheckForHeaderGuard(filename, lines, error):
 
   Args:
     filename: The name of the C++ header file.
-    lines: An array of strings, each representing a line of the file.
+    clean_lines: A CleansedLines instance containing the file.
     error: The function to call with any errors found.
   """
 
+  # Don't check for header guards if there are error suppression
+  # comments somewhere in this file.
+  #
+  # Because this is silencing a warning for a nonexistent line, we
+  # only support the very specific NOLINT(build/header_guard) syntax,
+  # and not the general NOLINT or NOLINT(*) syntax.
+  raw_lines = clean_lines.lines_without_raw_strings
+  for i in raw_lines:
+    if Search(r'//\s*NOLINT\(build/header_guard\)', i):
+      return
+
   cppvar = GetHeaderGuardCPPVariable(filename)
 
-  ifndef = None
+  ifndef = ''
   ifndef_linenum = 0
-  define = None
-  endif = None
+  define = ''
+  endif = ''
   endif_linenum = 0
-  for linenum, line in enumerate(lines):
+  for linenum, line in enumerate(raw_lines):
     linesplit = line.split()
     if len(linesplit) >= 2:
       # find the first occurrence of #ifndef and #define, save arg
@@ -1428,18 +1719,12 @@ def CheckForHeaderGuard(filename, lines, error):
       endif = line
       endif_linenum = linenum
 
-  if not ifndef:
+  if not ifndef or not define or ifndef != define:
     error(filename, 0, 'build/header_guard', 5,
           'No #ifndef header guard found, suggested CPP variable is: %s' %
           cppvar)
     return
 
-  if not define:
-    error(filename, 0, 'build/header_guard', 5,
-          'No #define header guard found, suggested CPP variable is: %s' %
-          cppvar)
-    return
-
   # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
   # for backward compatibility.
   if ifndef != cppvar:
@@ -1447,26 +1732,69 @@ def CheckForHeaderGuard(filename, lines, error):
     if ifndef != cppvar + '_':
       error_level = 5
 
-    ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum,
+    ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum,
                             error)
     error(filename, ifndef_linenum, 'build/header_guard', error_level,
           '#ifndef header guard has wrong style, please use: %s' % cppvar)
 
-  if define != ifndef:
-    error(filename, 0, 'build/header_guard', 5,
-          '#ifndef and #define don\'t match, suggested CPP variable is: %s' %
-          cppvar)
+  # Check for "//" comments on endif line.
+  ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum,
+                          error)
+  match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
+  if match:
+    if match.group(1) == '_':
+      # Issue low severity warning for deprecated double trailing underscore
+      error(filename, endif_linenum, 'build/header_guard', 0,
+            '#endif line should be "#endif  // %s"' % cppvar)
     return
 
-  if endif != ('#endif  // %s' % cppvar):
-    error_level = 0
-    if endif != ('#endif  // %s' % (cppvar + '_')):
-      error_level = 5
+  # Didn't find the corresponding "//" comment.  If this file does not
+  # contain any "//" comments at all, it could be that the compiler
+  # only wants "/**/" comments, look for those instead.
+  no_single_line_comments = True
+  for i in xrange(1, len(raw_lines) - 1):
+    line = raw_lines[i]
+    if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
+      no_single_line_comments = False
+      break
 
-    ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum,
-                            error)
-    error(filename, endif_linenum, 'build/header_guard', error_level,
-          '#endif line should be "#endif  // %s"' % cppvar)
+  if no_single_line_comments:
+    match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
+    if match:
+      if match.group(1) == '_':
+        # Low severity warning for double trailing underscore
+        error(filename, endif_linenum, 'build/header_guard', 0,
+              '#endif line should be "#endif  /* %s */"' % cppvar)
+      return
+
+  # Didn't find anything
+  error(filename, endif_linenum, 'build/header_guard', 5,
+        '#endif line should be "#endif  // %s"' % cppvar)
+
+
+def CheckHeaderFileIncluded(filename, include_state, error):
+  """Logs an error if a .cc file does not include its header."""
+
+  # Do not check test files
+  if filename.endswith('_test.cc') or filename.endswith('_unittest.cc'):
+    return
+
+  fileinfo = FileInfo(filename)
+  headerfile = filename[0:len(filename) - 2] + 'h'
+  if not os.path.exists(headerfile):
+    return
+  headername = FileInfo(headerfile).RepositoryName()
+  first_include = 0
+  for section_list in include_state.include_list:
+    for f in section_list:
+      if headername in f[0] or f[0] in headername:
+        return
+      if not first_include:
+        first_include = f[1]
+
+  error(filename, first_include, 'build/include', 5,
+        '%s should include its header file %s' % (fileinfo.RepositoryName(),
+                                                  headername))
 
 
 def CheckForBadCharacters(filename, lines, error):
@@ -1550,19 +1878,33 @@ def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
           'Use C++11 raw strings or concatenation instead.')
 
 
-threading_list = (
-    ('asctime(', 'asctime_r('),
-    ('ctime(', 'ctime_r('),
-    ('getgrgid(', 'getgrgid_r('),
-    ('getgrnam(', 'getgrnam_r('),
-    ('getlogin(', 'getlogin_r('),
-    ('getpwnam(', 'getpwnam_r('),
-    ('getpwuid(', 'getpwuid_r('),
-    ('gmtime(', 'gmtime_r('),
-    ('localtime(', 'localtime_r('),
-    ('rand(', 'rand_r('),
-    ('strtok(', 'strtok_r('),
-    ('ttyname(', 'ttyname_r('),
+# (non-threadsafe name, thread-safe alternative, validation pattern)
+#
+# The validation pattern is used to eliminate false positives such as:
+#  _rand();               // false positive due to substring match.
+#  ->rand();              // some member function rand().
+#  ACMRandom rand(seed);  // some variable named rand.
+#  ISAACRandom rand();    // another variable named rand.
+#
+# Basically we require the return value of these functions to be used
+# in some expression context on the same line by matching on some
+# operator before the function name.  This eliminates constructors and
+# member function calls.
+_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)'
+_THREADING_LIST = (
+    ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'),
+    ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'),
+    ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'),
+    ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'),
+    ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'),
+    ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'),
+    ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'),
+    ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'),
+    ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'),
+    ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'),
+    ('strtok(', 'strtok_r(',
+     _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'),
+    ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'),
     )
 
 
@@ -1582,14 +1924,13 @@ def CheckPosixThreading(filename, clean_lines, linenum, error):
     error: The function to call with any errors found.
   """
   line = clean_lines.elided[linenum]
-  for single_thread_function, multithread_safe_function in threading_list:
-    ix = line.find(single_thread_function)
-    # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
-    if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and
-                                line[ix - 1] not in ('_', '.', '>'))):
+  for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
+    # Additional pattern matching check to confirm that this is the
+    # function we are looking for
+    if Search(pattern, line):
       error(filename, linenum, 'runtime/threadsafe_fn', 2,
-            'Consider using ' + multithread_safe_function +
-            '...) instead of ' + single_thread_function +
+            'Consider using ' + multithread_safe_func +
+            '...) instead of ' + single_thread_func +
             '...) for improved thread safety.')
 
 
@@ -1611,7 +1952,6 @@ def CheckVlogArguments(filename, clean_lines, linenum, error):
           'VLOG() should be used with numeric verbosity level.  '
           'Use LOG() if you want symbolic severity levels.')
 
-
 # Matches invalid increment: *count++, which moves pointer instead of
 # incrementing a value.
 _RE_PATTERN_INVALID_INCREMENT = re.compile(
@@ -1640,6 +1980,20 @@ def CheckInvalidIncrement(filename, clean_lines, linenum, error):
           'Changing pointer instead of value (or unused value of operator*).')
 
 
+def IsMacroDefinition(clean_lines, linenum):
+  if Search(r'^#define', clean_lines[linenum]):
+    return True
+
+  if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]):
+    return True
+
+  return False
+
+
+def IsForwardClassDeclaration(clean_lines, linenum):
+  return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
+
+
 class _BlockInfo(object):
   """Stores information about a generic block of code."""
 
@@ -1647,6 +2001,7 @@ class _BlockInfo(object):
     self.seen_open_brace = seen_open_brace
     self.open_parentheses = 0
     self.inline_asm = _NO_ASM
+    self.check_namespace_indentation = False
 
   def CheckBegin(self, filename, clean_lines, linenum, error):
     """Run checks that applies to text up to the opening brace.
@@ -1676,6 +2031,24 @@ class _BlockInfo(object):
     """
     pass
 
+  def IsBlockInfo(self):
+    """Returns true if this block is a _BlockInfo.
+
+    This is convenient for verifying that an object is an instance of
+    a _BlockInfo, but not an instance of any of the derived classes.
+
+    Returns:
+      True for this class, False for derived classes.
+    """
+    return self.__class__ == _BlockInfo
+
+
+class _ExternCInfo(_BlockInfo):
+  """Stores information about an 'extern "C"' block."""
+
+  def __init__(self):
+    _BlockInfo.__init__(self, True)
+
 
 class _ClassInfo(_BlockInfo):
   """Stores information about a class."""
@@ -1685,6 +2058,7 @@ class _ClassInfo(_BlockInfo):
     self.name = name
     self.starting_linenum = linenum
     self.is_derived = False
+    self.check_namespace_indentation = True
     if class_or_struct == 'struct':
       self.access = 'public'
       self.is_struct = True
@@ -1694,11 +2068,7 @@ class _ClassInfo(_BlockInfo):
 
     # Remember initial indentation level for this class.  Using raw_lines here
     # instead of elided to account for leading comments.
-    initial_indent = Match(r'^( *)\S', clean_lines.raw_lines[linenum])
-    if initial_indent:
-      self.class_indent = len(initial_indent.group(1))
-    else:
-      self.class_indent = 0
+    self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum])
 
     # Try to find the end of the class.  This will be confused by things like:
     #   class A {
@@ -1720,6 +2090,23 @@ class _ClassInfo(_BlockInfo):
       self.is_derived = True
 
   def CheckEnd(self, filename, clean_lines, linenum, error):
+    # If there is a DISALLOW macro, it should appear near the end of
+    # the class.
+    seen_last_thing_in_class = False
+    for i in xrange(linenum - 1, self.starting_linenum, -1):
+      match = Search(
+          r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
+          self.name + r'\)',
+          clean_lines.elided[i])
+      if match:
+        if seen_last_thing_in_class:
+          error(filename, i, 'readability/constructors', 3,
+                match.group(1) + ' should be the last thing in the class')
+        break
+
+      if not Match(r'^\s*$', clean_lines.elided[i]):
+        seen_last_thing_in_class = True
+
     # Check that closing brace is aligned with beginning of the class.
     # Only do this if the closing brace is indented by only whitespaces.
     # This means we will not check single-line class definitions.
@@ -1740,6 +2127,7 @@ class _NamespaceInfo(_BlockInfo):
     _BlockInfo.__init__(self, False)
     self.name = name or ''
     self.starting_linenum = linenum
+    self.check_namespace_indentation = True
 
   def CheckEnd(self, filename, clean_lines, linenum, error):
     """Check end of namespace comments."""
@@ -1783,8 +2171,15 @@ class _NamespaceInfo(_BlockInfo):
     else:
       # Anonymous namespace
       if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
-        error(filename, linenum, 'readability/namespace', 5,
-              'Namespace should be terminated with "// namespace"')
+        # If "// namespace anonymous" or "// anonymous namespace (more text)",
+        # mention "// anonymous namespace" as an acceptable form
+        if Match(r'}.*\b(namespace anonymous|anonymous namespace)\b', line):
+          error(filename, linenum, 'readability/namespace', 5,
+                'Anonymous namespace should be terminated with "// namespace"'
+                ' or "// anonymous namespace"')
+        else:
+          error(filename, linenum, 'readability/namespace', 5,
+                'Anonymous namespace should be terminated with "// namespace"')
 
 
 class _PreprocessorInfo(object):
@@ -1801,7 +2196,7 @@ class _PreprocessorInfo(object):
     self.seen_else = False
 
 
-class _NestingState(object):
+class NestingState(object):
   """Holds states related to parsing braces."""
 
   def __init__(self):
@@ -1813,6 +2208,17 @@ class _NestingState(object):
     # - _BlockInfo: some other type of block.
     self.stack = []
 
+    # Top of the previous stack before each Update().
+    #
+    # Because the nesting_stack is updated at the end of each line, we
+    # had to do some convoluted checks to find out what is the current
+    # scope at the beginning of the line.  This check is simplified by
+    # saving the previous top of nesting stack.
+    #
+    # We could save the full stack, but we only need the top.  Copying
+    # the full nesting stack would slow down cpplint by ~10%.
+    self.previous_stack_top = []
+
     # Stack of _PreprocessorInfo objects.
     self.pp_stack = []
 
@@ -1833,6 +2239,82 @@ class _NestingState(object):
     """
     return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
 
+  def InExternC(self):
+    """Check if we are currently one level inside an 'extern "C"' block.
+
+    Returns:
+      True if top of the stack is an extern block, False otherwise.
+    """
+    return self.stack and isinstance(self.stack[-1], _ExternCInfo)
+
+  def InClassDeclaration(self):
+    """Check if we are currently one level inside a class or struct declaration.
+
+    Returns:
+      True if top of the stack is a class/struct, False otherwise.
+    """
+    return self.stack and isinstance(self.stack[-1], _ClassInfo)
+
+  def InAsmBlock(self):
+    """Check if we are currently one level inside an inline ASM block.
+
+    Returns:
+      True if the top of the stack is a block containing inline ASM.
+    """
+    return self.stack and self.stack[-1].inline_asm != _NO_ASM
+
+  def InTemplateArgumentList(self, clean_lines, linenum, pos):
+    """Check if current position is inside template argument list.
+
+    Args:
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      pos: position just after the suspected template argument.
+    Returns:
+      True if (linenum, pos) is inside template arguments.
+    """
+    while linenum < clean_lines.NumLines():
+      # Find the earliest character that might indicate a template argument
+      line = clean_lines.elided[linenum]
+      match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
+      if not match:
+        linenum += 1
+        pos = 0
+        continue
+      token = match.group(1)
+      pos += len(match.group(0))
+
+      # These things do not look like template argument list:
+      #   class Suspect {
+      #   class Suspect x; }
+      if token in ('{', '}', ';'): return False
+
+      # These things look like template argument list:
+      #   template <class Suspect>
+      #   template <class Suspect = default_value>
+      #   template <class Suspect[]>
+      #   template <class Suspect...>
+      if token in ('>', '=', '[', ']', '.'): return True
+
+      # Check if token is an unmatched '<'.
+      # If not, move on to the next character.
+      if token != '<':
+        pos += 1
+        if pos >= len(line):
+          linenum += 1
+          pos = 0
+        continue
+
+      # We can't be sure if we just find a single '<', and need to
+      # find the matching '>'.
+      (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1)
+      if end_pos < 0:
+        # Not sure if template argument list or syntax error in file
+        return False
+      linenum = end_line
+      pos = end_pos
+    return False
+
   def UpdatePreprocessor(self, line):
     """Update preprocessor stack.
 
@@ -1889,6 +2371,7 @@ class _NestingState(object):
         # TODO(unknown): unexpected #endif, issue warning?
         pass
 
+  # TODO(unknown): Update() is too long, but we will refactor later.
   def Update(self, filename, clean_lines, linenum, error):
     """Update nesting state with current line.
 
@@ -1900,7 +2383,17 @@ class _NestingState(object):
     """
     line = clean_lines.elided[linenum]
 
-    # Update pp_stack first
+    # Remember top of the previous nesting stack.
+    #
+    # The stack is always pushed/popped and not modified in place, so
+    # we can just do a shallow copy instead of copy.deepcopy.  Using
+    # deepcopy would slow down cpplint by ~28%.
+    if self.stack:
+      self.previous_stack_top = self.stack[-1]
+    else:
+      self.previous_stack_top = None
+
+    # Update pp_stack
     self.UpdatePreprocessor(line)
 
     # Count parentheses.  This is to avoid adding struct arguments to
@@ -1951,32 +2444,27 @@ class _NestingState(object):
     # such as in:
     #   class LOCKABLE API Object {
     #   };
-    #
-    # Templates with class arguments may confuse the parser, for example:
-    #   template <class T
-    #             class Comparator = less<T>,
-    #             class Vector = vector<T> >
-    #   class HeapQueue {
-    #
-    # Because this parser has no nesting state about templates, by the
-    # time it saw "class Comparator", it may think that it's a new class.
-    # Nested templates have a similar problem:
-    #   template <
-    #       typename ExportedType,
-    #       typename TupleType,
-    #       template <typename, typename> class ImplTemplate>
-    #
-    # To avoid these cases, we ignore classes that are followed by '=' or '>'
     class_decl_match = Match(
-        r'\s*(template\s*<[\w\s<>,:]*>\s*)?'
-        r'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)'
-        r'(([^=>]|<[^<>]*>|<[^<>]*<[^<>]*>\s*>)*)$', line)
+        r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?'
+        r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))'
+        r'(.*)$', line)
     if (class_decl_match and
         (not self.stack or self.stack[-1].open_parentheses == 0)):
-      self.stack.append(_ClassInfo(
-          class_decl_match.group(4), class_decl_match.group(2),
-          clean_lines, linenum))
-      line = class_decl_match.group(5)
+      # We do not want to accept classes that are actually template arguments:
+      #   template <class Ignore1,
+      #             class Ignore2 = Default<Args>,
+      #             template <Args> class Ignore3>
+      #   void Function() {};
+      #
+      # To avoid template argument cases, we scan forward and look for
+      # an unmatched '>'.  If we see one, assume we are inside a
+      # template argument list.
+      end_declaration = len(class_decl_match.group(1))
+      if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration):
+        self.stack.append(_ClassInfo(
+            class_decl_match.group(3), class_decl_match.group(2),
+            clean_lines, linenum))
+        line = class_decl_match.group(4)
 
     # If we have not yet seen the opening brace for the innermost block,
     # run checks here.
@@ -2023,10 +2511,13 @@ class _NestingState(object):
         # stack otherwise.
         if not self.SeenOpenBrace():
           self.stack[-1].seen_open_brace = True
+        elif Match(r'^extern\s*"[^"]*"\s*\{', line):
+          self.stack.append(_ExternCInfo())
         else:
           self.stack.append(_BlockInfo(True))
           if _MATCH_ASM.match(line):
             self.stack[-1].inline_asm = _BLOCK_ASM
+
       elif token == ';' or token == ')':
         # If we haven't seen an opening brace yet, but we already saw
         # a semicolon, this is probably a forward declaration.  Pop
@@ -2102,7 +2593,7 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
     filename: The name of the current file.
     clean_lines: A CleansedLines instance containing the file.
     linenum: The number of the line to check.
-    nesting_state: A _NestingState instance which maintains information about
+    nesting_state: A NestingState instance which maintains information about
                    the current stack of nested blocks being parsed.
     error: A callable to which errors are reported, which takes 4 arguments:
            filename, line number, error level, and message
@@ -2174,27 +2665,85 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
   base_classname = classinfo.name.split('::')[-1]
 
   # Look for single-argument constructors that aren't marked explicit.
-  # Technically a valid construct, but against style.
-  args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)'
-               % re.escape(base_classname),
-               line)
-  if (args and
-      args.group(1) != 'void' and
-      not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&'
-                % re.escape(base_classname), args.group(1).strip())):
-    error(filename, linenum, 'runtime/explicit', 5,
-          'Single-argument constructors should be marked explicit.')
-
-
-def CheckSpacingForFunctionCall(filename, line, linenum, error):
+  # Technically a valid construct, but against style. Also look for
+  # non-single-argument constructors which are also technically valid, but
+  # strongly suggest something is wrong.
+  explicit_constructor_match = Match(
+      r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*'
+      r'\(((?:[^()]|\([^()]*\))*)\)'
+      % re.escape(base_classname),
+      line)
+
+  if explicit_constructor_match:
+    is_marked_explicit = explicit_constructor_match.group(1)
+
+    if not explicit_constructor_match.group(2):
+      constructor_args = []
+    else:
+      constructor_args = explicit_constructor_match.group(2).split(',')
+
+    # collapse arguments so that commas in template parameter lists and function
+    # argument parameter lists don't split arguments in two
+    i = 0
+    while i < len(constructor_args):
+      constructor_arg = constructor_args[i]
+      while (constructor_arg.count('<') > constructor_arg.count('>') or
+             constructor_arg.count('(') > constructor_arg.count(')')):
+        constructor_arg += ',' + constructor_args[i + 1]
+        del constructor_args[i + 1]
+      constructor_args[i] = constructor_arg
+      i += 1
+
+    defaulted_args = [arg for arg in constructor_args if '=' in arg]
+    noarg_constructor = (not constructor_args or  # empty arg list
+                         # 'void' arg specifier
+                         (len(constructor_args) == 1 and
+                          constructor_args[0].strip() == 'void'))
+    onearg_constructor = ((len(constructor_args) == 1 and  # exactly one arg
+                           not noarg_constructor) or
+                          # all but at most one arg defaulted
+                          (len(constructor_args) >= 1 and
+                           not noarg_constructor and
+                           len(defaulted_args) >= len(constructor_args) - 1))
+    initializer_list_constructor = bool(
+        onearg_constructor and
+        Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
+    copy_constructor = bool(
+        onearg_constructor and
+        Match(r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
+              % re.escape(base_classname), constructor_args[0].strip()))
+
+    if (not is_marked_explicit and
+        onearg_constructor and
+        not initializer_list_constructor and
+        not copy_constructor):
+      if defaulted_args:
+        error(filename, linenum, 'runtime/explicit', 5,
+              'Constructors callable with one argument '
+              'should be marked explicit.')
+      else:
+        error(filename, linenum, 'runtime/explicit', 5,
+              'Single-parameter constructors should be marked explicit.')
+    elif is_marked_explicit and not onearg_constructor:
+      if noarg_constructor:
+        error(filename, linenum, 'runtime/explicit', 5,
+              'Zero-parameter constructors should not be marked explicit.')
+      else:
+        error(filename, linenum, 'runtime/explicit', 0,
+              'Constructors that require multiple arguments '
+              'should not be marked explicit.')
+
+
+def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
   """Checks for the correctness of various spacing around function calls.
 
   Args:
     filename: The name of the current file.
-    line: The text of the line to check.
+    clean_lines: A CleansedLines instance containing the file.
     linenum: The number of the line to check.
     error: The function to call with any errors found.
   """
+  line = clean_lines.elided[linenum]
 
   # Since function calls often occur inside if/for/while/switch
   # expressions - which have their own, more liberal conventions - we
@@ -2237,10 +2786,17 @@ def CheckSpacingForFunctionCall(filename, line, linenum, error):
       error(filename, linenum, 'whitespace/parens', 2,
             'Extra space after (')
     if (Search(r'\w\s+\(', fncall) and
-        not Search(r'#\s*define|typedef', fncall) and
-        not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall)):
-      error(filename, linenum, 'whitespace/parens', 4,
-            'Extra space before ( in function call')
+        not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
+        not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
+        not Search(r'\bcase\s+\(', fncall)):
+      # TODO(unknown): Space after an operator function seem to be a common
+      # error, silence those for now by restricting them to highest verbosity.
+      if Search(r'\boperator_*\b', line):
+        error(filename, linenum, 'whitespace/parens', 0,
+              'Extra space before ( in function call')
+      else:
+        error(filename, linenum, 'whitespace/parens', 4,
+              'Extra space before ( in function call')
     # If the ) is followed only by a newline or a { + newline, assume it's
     # part of a control statement (if/while/etc), and don't complain
     if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
@@ -2269,6 +2825,20 @@ def IsBlankLine(line):
   return not line or line.isspace()
 
 
+def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
+                                 error):
+  is_namespace_indent_item = (
+      len(nesting_state.stack) > 1 and
+      nesting_state.stack[-1].check_namespace_indentation and
+      isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and
+      nesting_state.previous_stack_top == nesting_state.stack[-2])
+
+  if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
+                                     clean_lines.elided, line):
+    CheckItemIndentationInNamespace(filename, clean_lines.elided,
+                                    line, error)
+
+
 def CheckForFunctionLengths(filename, clean_lines, linenum,
                             function_state, error):
   """Reports for long function bodies.
@@ -2294,8 +2864,6 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
   """
   lines = clean_lines.lines
   line = lines[linenum]
-  raw = clean_lines.raw_lines
-  raw_line = raw[linenum]
   joined_line = ''
 
   starting_func = False
@@ -2342,34 +2910,61 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
 _RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
 
 
-def CheckComment(comment, filename, linenum, error):
-  """Checks for common mistakes in TODO comments.
+def CheckComment(line, filename, linenum, next_line_start, error):
+  """Checks for common mistakes in comments.
 
   Args:
-    comment: The text of the comment from the line in question.
+    line: The line in question.
     filename: The name of the current file.
     linenum: The number of the line to check.
+    next_line_start: The first non-whitespace column of the next line.
     error: The function to call with any errors found.
   """
-  match = _RE_PATTERN_TODO.match(comment)
-  if match:
-    # One whitespace is correct; zero whitespace is handled elsewhere.
-    leading_whitespace = match.group(1)
-    if len(leading_whitespace) > 1:
-      error(filename, linenum, 'whitespace/todo', 2,
-            'Too many spaces before TODO')
-
-    username = match.group(2)
-    if not username:
-      error(filename, linenum, 'readability/todo', 2,
-            'Missing username in TODO; it should look like '
-            '"// TODO(my_username): Stuff."')
-
-    middle_whitespace = match.group(3)
-    # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
-    if middle_whitespace != ' ' and middle_whitespace != '':
-      error(filename, linenum, 'whitespace/todo', 2,
-            'TODO(my_username) should be followed by a space')
+  commentpos = line.find('//')
+  if commentpos != -1:
+    # Check if the // may be in quotes.  If so, ignore it
+    # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
+    if (line.count('"', 0, commentpos) -
+        line.count('\\"', 0, commentpos)) % 2 == 0:   # not in quotes
+      # Allow one space for new scopes, two spaces otherwise:
+      if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
+          ((commentpos >= 1 and
+            line[commentpos-1] not in string.whitespace) or
+           (commentpos >= 2 and
+            line[commentpos-2] not in string.whitespace))):
+        error(filename, linenum, 'whitespace/comments', 2,
+              'At least two spaces is best between code and comments')
+
+      # Checks for common mistakes in TODO comments.
+      comment = line[commentpos:]
+      match = _RE_PATTERN_TODO.match(comment)
+      if match:
+        # One whitespace is correct; zero whitespace is handled elsewhere.
+        leading_whitespace = match.group(1)
+        if len(leading_whitespace) > 1:
+          error(filename, linenum, 'whitespace/todo', 2,
+                'Too many spaces before TODO')
+
+        username = match.group(2)
+        if not username:
+          error(filename, linenum, 'readability/todo', 2,
+                'Missing username in TODO; it should look like '
+                '"// TODO(my_username): Stuff."')
+
+        middle_whitespace = match.group(3)
+        # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
+        if middle_whitespace != ' ' and middle_whitespace != '':
+          error(filename, linenum, 'whitespace/todo', 2,
+                'TODO(my_username) should be followed by a space')
+
+      # If the comment contains an alphanumeric character, there
+      # should be a space somewhere between it and the // unless
+      # it's a /// or //! Doxygen comment.
+      if (Match(r'//[^ ]*\w', comment) and
+          not Match(r'(///|//\!)(\s+|$)', comment)):
+        error(filename, linenum, 'whitespace/comments', 4,
+              'Should have a space between // and comment')
+
 
 def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
   """Checks for improper use of DISALLOW* macros.
@@ -2378,14 +2973,13 @@ def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
     filename: The name of the current file.
     clean_lines: A CleansedLines instance containing the file.
     linenum: The number of the line to check.
-    nesting_state: A _NestingState instance which maintains information about
+    nesting_state: A NestingState instance which maintains information about
                    the current stack of nested blocks being parsed.
     error: The function to call with any errors found.
   """
   line = clean_lines.elided[linenum]  # get rid of comments and strings
 
   matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|'
-                   r'DISALLOW_EVIL_CONSTRUCTORS|'
                    r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
   if not matched:
     return
@@ -2402,132 +2996,6 @@ def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
     pass
 
 
-def FindNextMatchingAngleBracket(clean_lines, linenum, init_suffix):
-  """Find the corresponding > to close a template.
-
-  Args:
-    clean_lines: A CleansedLines instance containing the file.
-    linenum: Current line number.
-    init_suffix: Remainder of the current line after the initial <.
-
-  Returns:
-    True if a matching bracket exists.
-  """
-  line = init_suffix
-  nesting_stack = ['<']
-  while True:
-    # Find the next operator that can tell us whether < is used as an
-    # opening bracket or as a less-than operator.  We only want to
-    # warn on the latter case.
-    #
-    # We could also check all other operators and terminate the search
-    # early, e.g. if we got something like this "a<b+c", the "<" is
-    # most likely a less-than operator, but then we will get false
-    # positives for default arguments and other template expressions.
-    match = Search(r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line)
-    if match:
-      # Found an operator, update nesting stack
-      operator = match.group(1)
-      line = match.group(2)
-
-      if nesting_stack[-1] == '<':
-        # Expecting closing angle bracket
-        if operator in ('<', '(', '['):
-          nesting_stack.append(operator)
-        elif operator == '>':
-          nesting_stack.pop()
-          if not nesting_stack:
-            # Found matching angle bracket
-            return True
-        elif operator == ',':
-          # Got a comma after a bracket, this is most likely a template
-          # argument.  We have not seen a closing angle bracket yet, but
-          # it's probably a few lines later if we look for it, so just
-          # return early here.
-          return True
-        else:
-          # Got some other operator.
-          return False
-
-      else:
-        # Expecting closing parenthesis or closing bracket
-        if operator in ('<', '(', '['):
-          nesting_stack.append(operator)
-        elif operator in (')', ']'):
-          # We don't bother checking for matching () or [].  If we got
-          # something like (] or [), it would have been a syntax error.
-          nesting_stack.pop()
-
-    else:
-      # Scan the next line
-      linenum += 1
-      if linenum >= len(clean_lines.elided):
-        break
-      line = clean_lines.elided[linenum]
-
-  # Exhausted all remaining lines and still no matching angle bracket.
-  # Most likely the input was incomplete, otherwise we should have
-  # seen a semicolon and returned early.
-  return True
-
-
-def FindPreviousMatchingAngleBracket(clean_lines, linenum, init_prefix):
-  """Find the corresponding < that started a template.
-
-  Args:
-    clean_lines: A CleansedLines instance containing the file.
-    linenum: Current line number.
-    init_prefix: Part of the current line before the initial >.
-
-  Returns:
-    True if a matching bracket exists.
-  """
-  line = init_prefix
-  nesting_stack = ['>']
-  while True:
-    # Find the previous operator
-    match = Search(r'^(.*)([<>(),;\[\]])[^<>(),;\[\]]*$', line)
-    if match:
-      # Found an operator, update nesting stack
-      operator = match.group(2)
-      line = match.group(1)
-
-      if nesting_stack[-1] == '>':
-        # Expecting opening angle bracket
-        if operator in ('>', ')', ']'):
-          nesting_stack.append(operator)
-        elif operator == '<':
-          nesting_stack.pop()
-          if not nesting_stack:
-            # Found matching angle bracket
-            return True
-        elif operator == ',':
-          # Got a comma before a bracket, this is most likely a
-          # template argument.  The opening angle bracket is probably
-          # there if we look for it, so just return early here.
-          return True
-        else:
-          # Got some other operator.
-          return False
-
-      else:
-        # Expecting opening parenthesis or opening bracket
-        if operator in ('>', ')', ']'):
-          nesting_stack.append(operator)
-        elif operator in ('(', '['):
-          nesting_stack.pop()
-
-    else:
-      # Scan the previous line
-      linenum -= 1
-      if linenum < 0:
-        break
-      line = clean_lines.elided[linenum]
-
-  # Exhausted all earlier lines and still no matching angle bracket.
-  return False
-
-
 def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
   """Checks for the correctness of various spacing issues in the code.
 
@@ -2541,7 +3009,7 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
     filename: The name of the current file.
     clean_lines: A CleansedLines instance containing the file.
     linenum: The number of the line to check.
-    nesting_state: A _NestingState instance which maintains information about
+    nesting_state: A NestingState instance which maintains information about
                    the current stack of nested blocks being parsed.
     error: The function to call with any errors found.
   """
@@ -2564,7 +3032,12 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
   #   }
   #
   # A warning about missing end of namespace comments will be issued instead.
-  if IsBlankLine(line) and not nesting_state.InNamespaceBody():
+  #
+  # Also skip blank line checks for 'extern "C"' blocks, which are formatted
+  # like namespaces.
+  if (IsBlankLine(line) and
+      not nesting_state.InNamespaceBody() and
+      not nesting_state.InExternC()):
     elided = clean_lines.elided
     prev_line = elided[linenum - 1]
     prevbrace = prev_line.rfind('{')
@@ -2627,54 +3100,64 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
       error(filename, linenum, 'whitespace/blank_line', 3,
             'Do not leave a blank line after "%s:"' % matched.group(1))
 
-  # Next, we complain if there's a comment too near the text
-  commentpos = line.find('//')
-  if commentpos != -1:
-    # Check if the // may be in quotes.  If so, ignore it
-    # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
-    if (line.count('"', 0, commentpos) -
-        line.count('\\"', 0, commentpos)) % 2 == 0:   # not in quotes
-      # Allow one space for new scopes, two spaces otherwise:
-      if (not Match(r'^\s*{ //', line) and
-          ((commentpos >= 1 and
-            line[commentpos-1] not in string.whitespace) or
-           (commentpos >= 2 and
-            line[commentpos-2] not in string.whitespace))):
-        error(filename, linenum, 'whitespace/comments', 2,
-              'At least two spaces is best between code and comments')
-      # There should always be a space between the // and the comment
-      commentend = commentpos + 2
-      if commentend < len(line) and not line[commentend] == ' ':
-        # but some lines are exceptions -- e.g. if they're big
-        # comment delimiters like:
-        # //----------------------------------------------------------
-        # or are an empty C++ style Doxygen comment, like:
-        # ///
-        # or C++ style Doxygen comments placed after the variable:
-        # ///<  Header comment
-        # //!<  Header comment
-        # or they begin with multiple slashes followed by a space:
-        # //////// Header comment
-        match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or
-                 Search(r'^/$', line[commentend:]) or
-                 Search(r'^!< ', line[commentend:]) or
-                 Search(r'^/< ', line[commentend:]) or
-                 Search(r'^/+ ', line[commentend:]))
-        if not match:
-          error(filename, linenum, 'whitespace/comments', 4,
-                'Should have a space between // and comment')
-      CheckComment(line[commentpos:], filename, linenum, error)
+  # Next, check comments
+  next_line_start = 0
+  if linenum + 1 < clean_lines.NumLines():
+    next_line = raw[linenum + 1]
+    next_line_start = len(next_line) - len(next_line.lstrip())
+  CheckComment(line, filename, linenum, next_line_start, error)
 
-  line = clean_lines.elided[linenum]  # get rid of comments and strings
+  # get rid of comments and strings
+  line = clean_lines.elided[linenum]
+
+  # You shouldn't have spaces before your brackets, except maybe after
+  # 'delete []' or 'return []() {};'
+  if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line):
+    error(filename, linenum, 'whitespace/braces', 5,
+          'Extra space before [')
+
+  # In range-based for, we wanted spaces before and after the colon, but
+  # not around "::" tokens that might appear.
+  if (Search(r'for *\(.*[^:]:[^: ]', line) or
+      Search(r'for *\(.*[^: ]:[^:]', line)):
+    error(filename, linenum, 'whitespace/forcolon', 2,
+          'Missing space around colon in range-based for loop')
+
+
+def CheckOperatorSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing around operators.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
 
-  # Don't try to do spacing checks for operator methods
-  line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line)
+  # Don't try to do spacing checks for operator methods.  Do this by
+  # replacing the troublesome characters with something else,
+  # preserving column position for all other characters.
+  #
+  # The replacement is done repeatedly to avoid false positives from
+  # operators that call operators.
+  while True:
+    match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
+    if match:
+      line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
+    else:
+      break
 
   # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
   # Otherwise not.  Note we only check for non-spaces on *both* sides;
   # sometimes people put non-spaces on one side when aligning ='s among
   # many lines (not that this is behavior that I approve of...)
-  if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line):
+  if ((Search(r'[\w.]=', line) or
+       Search(r'=[\w.]', line))
+      and not Search(r'\b(if|while|for) ', line)
+      # Operators taken from [lex.operators] in C++11 standard.
+      and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
+      and not Search(r'operator=', line)):
     error(filename, linenum, 'whitespace/operators', 4,
           'Missing spaces around =')
 
@@ -2686,42 +3169,51 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
   #
   # Check <= and >= first to avoid false positives with < and >, then
   # check non-include lines for spacing around < and >.
-  match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line)
+  #
+  # If the operator is followed by a comma, assume it's be used in a
+  # macro context and don't do any checks.  This avoids false
+  # positives.
+  #
+  # Note that && is not included here.  Those are checked separately
+  # in CheckRValueReference
+  match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
   if match:
     error(filename, linenum, 'whitespace/operators', 3,
           'Missing spaces around %s' % match.group(1))
-  # We allow no-spaces around << when used like this: 10<<20, but
-  # not otherwise (particularly, not when used as streams)
-  # Also ignore using ns::operator<<;
-  match = Search(r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line)
-  if (match and
-      not (match.group(1).isdigit() and match.group(2).isdigit()) and
-      not (match.group(1) == 'operator' and match.group(2) == ';')):
-    error(filename, linenum, 'whitespace/operators', 3,
-          'Missing spaces around <<')
   elif not Match(r'#.*include', line):
-    # Avoid false positives on ->
-    reduced_line = line.replace('->', '')
-
     # Look for < that is not surrounded by spaces.  This is only
     # triggered if both sides are missing spaces, even though
     # technically should should flag if at least one side is missing a
     # space.  This is done to avoid some false positives with shifts.
-    match = Search(r'[^\s<]<([^\s=<].*)', reduced_line)
-    if (match and
-        not FindNextMatchingAngleBracket(clean_lines, linenum, match.group(1))):
-      error(filename, linenum, 'whitespace/operators', 3,
-            'Missing spaces around <')
+    match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
+    if match:
+      (_, _, end_pos) = CloseExpression(
+          clean_lines, linenum, len(match.group(1)))
+      if end_pos <= -1:
+        error(filename, linenum, 'whitespace/operators', 3,
+              'Missing spaces around <')
 
     # Look for > that is not surrounded by spaces.  Similar to the
     # above, we only trigger if both sides are missing spaces to avoid
     # false positives with shifts.
-    match = Search(r'^(.*[^\s>])>[^\s=>]', reduced_line)
-    if (match and
-        not FindPreviousMatchingAngleBracket(clean_lines, linenum,
-                                             match.group(1))):
-      error(filename, linenum, 'whitespace/operators', 3,
-            'Missing spaces around >')
+    match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
+    if match:
+      (_, _, start_pos) = ReverseCloseExpression(
+          clean_lines, linenum, len(match.group(1)))
+      if start_pos <= -1:
+        error(filename, linenum, 'whitespace/operators', 3,
+              'Missing spaces around >')
+
+  # We allow no-spaces around << when used like this: 10<<20, but
+  # not otherwise (particularly, not when used as streams)
+  #
+  # We also allow operators following an opening parenthesis, since
+  # those tend to be macros that deal with operators.
+  match = Search(r'(operator|[^\s(<])(?:L|UL|ULL|l|ul|ull)?<<([^\s,=<])', line)
+  if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
+      not (match.group(1) == 'operator' and match.group(2) == ';')):
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around <<')
 
   # We allow no-spaces around >> for almost anything.  This is because
   # C++11 allows ">>" to close nested templates, which accounts for
@@ -2746,7 +3238,19 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
     error(filename, linenum, 'whitespace/operators', 4,
           'Extra space for operator %s' % match.group(1))
 
-  # A pet peeve of mine: no spaces after an if, while, switch, or for
+
+def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing around parentheses.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # No spaces after an if, while, switch, or for
   match = Search(r' (if\(|for\(|while\(|switch\()', line)
   if match:
     error(filename, linenum, 'whitespace/parens', 5,
@@ -2772,6 +3276,19 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
             'Should have zero or one spaces inside ( and ) in %s' %
             match.group(1))
 
+
+def CheckCommaSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing near commas and semicolons.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  raw = clean_lines.lines_without_raw_strings
+  line = clean_lines.elided[linenum]
+
   # You should always have a space after a comma (either as fn arg or operator)
   #
   # This does not apply when the non-space character following the
@@ -2782,7 +3299,8 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
   # verify that lines contain missing whitespaces, second pass on raw
   # lines to confirm that those missing whitespaces are not due to
   # elided comments.
-  if Search(r',[^,\s]', line) and Search(r',[^,\s]', raw[linenum]):
+  if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and
+      Search(r',[^,\s]', raw[linenum])):
     error(filename, linenum, 'whitespace/comma', 3,
           'Missing space after ,')
 
@@ -2794,14 +3312,23 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
     error(filename, linenum, 'whitespace/semicolon', 3,
           'Missing space after ;')
 
-  # Next we will look for issues with function calls.
-  CheckSpacingForFunctionCall(filename, line, linenum, error)
+
+def CheckBracesSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing near commas.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
 
   # Except after an opening paren, or after another opening brace (in case of
   # an initializer list, for instance), you should have spaces before your
   # braces. And since you should never have braces at the beginning of a line,
   # this is an easy test.
-  match = Match(r'^(.*[^ ({]){', line)
+  match = Match(r'^(.*[^ ({>]){', line)
   if match:
     # Try a bit harder to check for brace initialization.  This
     # happens in one of the following forms:
@@ -2812,10 +3339,12 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
     #   LastArgument(..., type{});
     #   LOG(INFO) << type{} << " ...";
     #   map_of_type[{...}] = ...;
+    #   ternary = expr ? new type{} : nullptr;
+    #   OuterTemplate<InnerTemplateConstructor<Type>{}>
     #
     # We check for the character following the closing brace, and
     # silence the warning if it's one of those listed above, i.e.
-    # "{.;,)<]".
+    # "{.;,)<>]:".
     #
     # To account for nested initializer list, we allow any number of
     # closing braces up to "{;,)<".  We can't simply silence the
@@ -2837,7 +3366,7 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
     for offset in xrange(endlinenum + 1,
                          min(endlinenum + 3, clean_lines.NumLines() - 1)):
       trailing_text += clean_lines.elided[offset]
-    if not Match(r'^[\s}]*[{.;,)<\]]', trailing_text):
+    if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text):
       error(filename, linenum, 'whitespace/braces', 5,
             'Missing space before {')
 
@@ -2846,12 +3375,6 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
     error(filename, linenum, 'whitespace/braces', 5,
           'Missing space before else')
 
-  # You shouldn't have spaces before your brackets, except maybe after
-  # 'delete []' or 'new char * []'.
-  if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line):
-    error(filename, linenum, 'whitespace/braces', 5,
-          'Extra space before [')
-
   # You shouldn't have a space before a semicolon at the end of the line.
   # There's a special case for "for" since the style guide allows space before
   # the semicolon there.
@@ -2868,12 +3391,422 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
           'Extra space before last semicolon. If this should be an empty '
           'statement, use {} instead.')
 
-  # In range-based for, we wanted spaces before and after the colon, but
-  # not around "::" tokens that might appear.
-  if (Search('for *\(.*[^:]:[^: ]', line) or
-      Search('for *\(.*[^: ]:[^:]', line)):
-    error(filename, linenum, 'whitespace/forcolon', 2,
-          'Missing space around colon in range-based for loop')
+
+def IsDecltype(clean_lines, linenum, column):
+  """Check if the token ending on (linenum, column) is decltype().
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: the number of the line to check.
+    column: end column of the token to check.
+  Returns:
+    True if this token is decltype() expression, False otherwise.
+  """
+  (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
+  if start_col < 0:
+    return False
+  if Search(r'\bdecltype\s*$', text[0:start_col]):
+    return True
+  return False
+
+
+def IsTemplateParameterList(clean_lines, linenum, column):
+  """Check if the token ending on (linenum, column) is the end of template<>.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: the number of the line to check.
+    column: end column of the token to check.
+  Returns:
+    True if this token is end of a template parameter list, False otherwise.
+  """
+  (_, startline, startpos) = ReverseCloseExpression(
+      clean_lines, linenum, column)
+  if (startpos > -1 and
+      Search(r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])):
+    return True
+  return False
+
+
+def IsRValueType(typenames, clean_lines, nesting_state, linenum, column):
+  """Check if the token ending on (linenum, column) is a type.
+
+  Assumes that text to the right of the column is "&&" or a function
+  name.
+
+  Args:
+    typenames: set of type names from template-argument-list.
+    clean_lines: A CleansedLines instance containing the file.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    linenum: the number of the line to check.
+    column: end column of the token to check.
+  Returns:
+    True if this token is a type, False if we are not sure.
+  """
+  prefix = clean_lines.elided[linenum][0:column]
+
+  # Get one word to the left.  If we failed to do so, this is most
+  # likely not a type, since it's unlikely that the type name and "&&"
+  # would be split across multiple lines.
+  match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix)
+  if not match:
+    return False
+
+  # Check text following the token.  If it's "&&>" or "&&," or "&&...", it's
+  # most likely a rvalue reference used inside a template.
+  suffix = clean_lines.elided[linenum][column:]
+  if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix):
+    return True
+
+  # Check for known types and end of templates:
+  #   int&& variable
+  #   vector<int>&& variable
+  #
+  # Because this function is called recursively, we also need to
+  # recognize pointer and reference types:
+  #   int* Function()
+  #   int& Function()
+  if (match.group(2) in typenames or
+      match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool',
+                         'short', 'int', 'long', 'signed', 'unsigned',
+                         'float', 'double', 'void', 'auto', '>', '*', '&']):
+    return True
+
+  # If we see a close parenthesis, look for decltype on the other side.
+  # decltype would unambiguously identify a type, anything else is
+  # probably a parenthesized expression and not a type.
+  if match.group(2) == ')':
+    return IsDecltype(
+        clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1)
+
+  # Check for casts and cv-qualifiers.
+  #   match.group(1)  remainder
+  #   --------------  ---------
+  #   const_cast<     type&&
+  #   const           type&&
+  #   type            const&&
+  if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|'
+            r'reinterpret_cast\s*<|\w+\s)\s*$',
+            match.group(1)):
+    return True
+
+  # Look for a preceding symbol that might help differentiate the context.
+  # These are the cases that would be ambiguous:
+  #   match.group(1)  remainder
+  #   --------------  ---------
+  #   Call         (   expression &&
+  #   Declaration  (   type&&
+  #   sizeof       (   type&&
+  #   if           (   expression &&
+  #   while        (   expression &&
+  #   for          (   type&&
+  #   for(         ;   expression &&
+  #   statement    ;   type&&
+  #   block        {   type&&
+  #   constructor  {   expression &&
+  start = linenum
+  line = match.group(1)
+  match_symbol = None
+  while start >= 0:
+    # We want to skip over identifiers and commas to get to a symbol.
+    # Commas are skipped so that we can find the opening parenthesis
+    # for function parameter lists.
+    match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line)
+    if match_symbol:
+      break
+    start -= 1
+    line = clean_lines.elided[start]
+
+  if not match_symbol:
+    # Probably the first statement in the file is an rvalue reference
+    return True
+
+  if match_symbol.group(2) == '}':
+    # Found closing brace, probably an indicate of this:
+    #   block{} type&&
+    return True
+
+  if match_symbol.group(2) == ';':
+    # Found semicolon, probably one of these:
+    #   for(; expression &&
+    #   statement; type&&
+
+    # Look for the previous 'for(' in the previous lines.
+    before_text = match_symbol.group(1)
+    for i in xrange(start - 1, max(start - 6, 0), -1):
+      before_text = clean_lines.elided[i] + before_text
+    if Search(r'for\s*\([^{};]*$', before_text):
+      # This is the condition inside a for-loop
+      return False
+
+    # Did not find a for-init-statement before this semicolon, so this
+    # is probably a new statement and not a condition.
+    return True
+
+  if match_symbol.group(2) == '{':
+    # Found opening brace, probably one of these:
+    #   block{ type&& = ... ; }
+    #   constructor{ expression && expression }
+
+    # Look for a closing brace or a semicolon.  If we see a semicolon
+    # first, this is probably a rvalue reference.
+    line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1]
+    end = start
+    depth = 1
+    while True:
+      for ch in line:
+        if ch == ';':
+          return True
+        elif ch == '{':
+          depth += 1
+        elif ch == '}':
+          depth -= 1
+          if depth == 0:
+            return False
+      end += 1
+      if end >= clean_lines.NumLines():
+        break
+      line = clean_lines.elided[end]
+    # Incomplete program?
+    return False
+
+  if match_symbol.group(2) == '(':
+    # Opening parenthesis.  Need to check what's to the left of the
+    # parenthesis.  Look back one extra line for additional context.
+    before_text = match_symbol.group(1)
+    if linenum > 1:
+      before_text = clean_lines.elided[linenum - 1] + before_text
+    before_text = match_symbol.group(1)
+
+    # Patterns that are likely to be types:
+    #   [](type&&
+    #   for (type&&
+    #   sizeof(type&&
+    #   operator=(type&&
+    #
+    if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text):
+      return True
+
+    # Patterns that are likely to be expressions:
+    #   if (expression &&
+    #   while (expression &&
+    #   : initializer(expression &&
+    #   , initializer(expression &&
+    #   ( FunctionCall(expression &&
+    #   + FunctionCall(expression &&
+    #   + (expression &&
+    #
+    # The last '+' represents operators such as '+' and '-'.
+    if Search(r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text):
+      return False
+
+    # Something else.  Check that tokens to the left look like
+    #   return_type function_name
+    match_func = Match(r'^(.*\S.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$',
+                       match_symbol.group(1))
+    if match_func:
+      # Check for constructors, which don't have return types.
+      if Search(r'\b(?:explicit|inline)$', match_func.group(1)):
+        return True
+      implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix)
+      if (implicit_constructor and
+          implicit_constructor.group(1) == implicit_constructor.group(2)):
+        return True
+      return IsRValueType(typenames, clean_lines, nesting_state, linenum,
+                          len(match_func.group(1)))
+
+    # Nothing before the function name.  If this is inside a block scope,
+    # this is probably a function call.
+    return not (nesting_state.previous_stack_top and
+                nesting_state.previous_stack_top.IsBlockInfo())
+
+  if match_symbol.group(2) == '>':
+    # Possibly a closing bracket, check that what's on the other side
+    # looks like the start of a template.
+    return IsTemplateParameterList(
+        clean_lines, start, len(match_symbol.group(1)))
+
+  # Some other symbol, usually something like "a=b&&c".  This is most
+  # likely not a type.
+  return False
+
+
+def IsDeletedOrDefault(clean_lines, linenum):
+  """Check if current constructor or operator is deleted or default.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if this is a deleted or default constructor.
+  """
+  open_paren = clean_lines.elided[linenum].find('(')
+  if open_paren < 0:
+    return False
+  (close_line, _, close_paren) = CloseExpression(
+      clean_lines, linenum, open_paren)
+  if close_paren < 0:
+    return False
+  return Match(r'\s*=\s*(?:delete|default)\b', close_line[close_paren:])
+
+
+def IsRValueAllowed(clean_lines, linenum, typenames):
+  """Check if RValue reference is allowed on a particular line.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    typenames: set of type names from template-argument-list.
+  Returns:
+    True if line is within the region where RValue references are allowed.
+  """
+  # Allow region marked by PUSH/POP macros
+  for i in xrange(linenum, 0, -1):
+    line = clean_lines.elided[i]
+    if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
+      if not line.endswith('PUSH'):
+        return False
+      for j in xrange(linenum, clean_lines.NumLines(), 1):
+        line = clean_lines.elided[j]
+        if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
+          return line.endswith('POP')
+
+  # Allow operator=
+  line = clean_lines.elided[linenum]
+  if Search(r'\boperator\s*=\s*\(', line):
+    return IsDeletedOrDefault(clean_lines, linenum)
+
+  # Allow constructors
+  match = Match(r'\s*(?:[\w<>]+::)*([\w<>]+)\s*::\s*([\w<>]+)\s*\(', line)
+  if match and match.group(1) == match.group(2):
+    return IsDeletedOrDefault(clean_lines, linenum)
+  if Search(r'\b(?:explicit|inline)\s+[\w<>]+\s*\(', line):
+    return IsDeletedOrDefault(clean_lines, linenum)
+
+  if Match(r'\s*[\w<>]+\s*\(', line):
+    previous_line = 'ReturnType'
+    if linenum > 0:
+      previous_line = clean_lines.elided[linenum - 1]
+    if Match(r'^\s*$', previous_line) or Search(r'[{}:;]\s*$', previous_line):
+      return IsDeletedOrDefault(clean_lines, linenum)
+
+  # Reject types not mentioned in template-argument-list
+  while line:
+    match = Match(r'^.*?(\w+)\s*&&(.*)$', line)
+    if not match:
+      break
+    if match.group(1) not in typenames:
+      return False
+    line = match.group(2)
+
+  # All RValue types that were in template-argument-list should have
+  # been removed by now.  Those were allowed, assuming that they will
+  # be forwarded.
+  #
+  # If there are no remaining RValue types left (i.e. types that were
+  # not found in template-argument-list), flag those as not allowed.
+  return line.find('&&') < 0
+
+
+def GetTemplateArgs(clean_lines, linenum):
+  """Find list of template arguments associated with this function declaration.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: Line number containing the start of the function declaration,
+             usually one line after the end of the template-argument-list.
+  Returns:
+    Set of type names, or empty set if this does not appear to have
+    any template parameters.
+  """
+  # Find start of function
+  func_line = linenum
+  while func_line > 0:
+    line = clean_lines.elided[func_line]
+    if Match(r'^\s*$', line):
+      return set()
+    if line.find('(') >= 0:
+      break
+    func_line -= 1
+  if func_line == 0:
+    return set()
+
+  # Collapse template-argument-list into a single string
+  argument_list = ''
+  match = Match(r'^(\s*template\s*)<', clean_lines.elided[func_line])
+  if match:
+    # template-argument-list on the same line as function name
+    start_col = len(match.group(1))
+    _, end_line, end_col = CloseExpression(clean_lines, func_line, start_col)
+    if end_col > -1 and end_line == func_line:
+      start_col += 1  # Skip the opening bracket
+      argument_list = clean_lines.elided[func_line][start_col:end_col]
+
+  elif func_line > 1:
+    # template-argument-list one line before function name
+    match = Match(r'^(.*)>\s*$', clean_lines.elided[func_line - 1])
+    if match:
+      end_col = len(match.group(1))
+      _, start_line, start_col = ReverseCloseExpression(
+          clean_lines, func_line - 1, end_col)
+      if start_col > -1:
+        start_col += 1  # Skip the opening bracket
+        while start_line < func_line - 1:
+          argument_list += clean_lines.elided[start_line][start_col:]
+          start_col = 0
+          start_line += 1
+        argument_list += clean_lines.elided[func_line - 1][start_col:end_col]
+
+  if not argument_list:
+    return set()
+
+  # Extract type names
+  typenames = set()
+  while True:
+    match = Match(r'^[,\s]*(?:typename|class)(?:\.\.\.)?\s+(\w+)(.*)$',
+                  argument_list)
+    if not match:
+      break
+    typenames.add(match.group(1))
+    argument_list = match.group(2)
+  return typenames
+
+
+def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error):
+  """Check for rvalue references.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+  # Find lines missing spaces around &&.
+  # TODO(unknown): currently we don't check for rvalue references
+  # with spaces surrounding the && to avoid false positives with
+  # boolean expressions.
+  line = clean_lines.elided[linenum]
+  match = Match(r'^(.*\S)&&', line)
+  if not match:
+    match = Match(r'(.*)&&\S', line)
+  if (not match) or '(&&)' in line or Search(r'\boperator\s*$', match.group(1)):
+    return
+
+  # Either poorly formed && or an rvalue reference, check the context
+  # to get a more accurate error message.  Mostly we want to determine
+  # if what's to the left of "&&" is a type or not.
+  typenames = GetTemplateArgs(clean_lines, linenum)
+  and_pos = len(match.group(1))
+  if IsRValueType(typenames, clean_lines, nesting_state, linenum, and_pos):
+    if not IsRValueAllowed(clean_lines, linenum, typenames):
+      error(filename, linenum, 'build/c++11', 3,
+            'RValue references are an unapproved C++ feature.')
+  else:
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around &&')
 
 
 def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
@@ -2981,7 +3914,7 @@ def CheckBraces(filename, clean_lines, linenum, error):
             '{ should almost always be at the end of the previous line')
 
   # An else clause should be on the same line as the preceding closing brace.
-  if Match(r'\s*else\s*', line):
+  if Match(r'\s*else\b\s*(?:if\b|\{|$)', line):
     prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
     if Match(r'\s*}\s*$', prevline):
       error(filename, linenum, 'whitespace/newline', 4,
@@ -2989,19 +3922,20 @@ def CheckBraces(filename, clean_lines, linenum, error):
 
   # If braces come on one side of an else, they should be on both.
   # However, we have to worry about "else if" that spans multiple lines!
-  if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
-    if Search(r'}\s*else if([^{]*)$', line):       # could be multi-line if
-      # find the ( after the if
-      pos = line.find('else if')
-      pos = line.find('(', pos)
-      if pos > 0:
-        (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
-        if endline[endpos:].find('{') == -1:    # must be brace after if
-          error(filename, linenum, 'readability/braces', 5,
-                'If an else has a brace on one side, it should have it on both')
-    else:            # common case: else not followed by a multi-line if
-      error(filename, linenum, 'readability/braces', 5,
-            'If an else has a brace on one side, it should have it on both')
+  if Search(r'else if\s*\(', line):       # could be multi-line if
+    brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
+    # find the ( after the if
+    pos = line.find('else if')
+    pos = line.find('(', pos)
+    if pos > 0:
+      (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
+      brace_on_right = endline[endpos:].find('{') != -1
+      if brace_on_left != brace_on_right:    # must be brace after if
+        error(filename, linenum, 'readability/braces', 5,
+              'If an else has a brace on one side, it should have it on both')
+  elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
+    error(filename, linenum, 'readability/braces', 5,
+          'If an else has a brace on one side, it should have it on both')
 
   # Likewise, an else should never have the else clause on the same line
   if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
@@ -3013,6 +3947,74 @@ def CheckBraces(filename, clean_lines, linenum, error):
     error(filename, linenum, 'whitespace/newline', 4,
           'do/while clauses should not be on a single line')
 
+  # Check single-line if/else bodies. The style guide says 'curly braces are not
+  # required for single-line statements'. We additionally allow multi-line,
+  # single statements, but we reject anything with more than one semicolon in
+  # it. This means that the first semicolon after the if should be at the end of
+  # its line, and the line after that should have an indent level equal to or
+  # lower than the if. We also check for ambiguous if/else nesting without
+  # braces.
+  if_else_match = Search(r'\b(if\s*\(|else\b)', line)
+  if if_else_match and not Match(r'\s*#', line):
+    if_indent = GetIndentLevel(line)
+    endline, endlinenum, endpos = line, linenum, if_else_match.end()
+    if_match = Search(r'\bif\s*\(', line)
+    if if_match:
+      # This could be a multiline if condition, so find the end first.
+      pos = if_match.end() - 1
+      (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
+    # Check for an opening brace, either directly after the if or on the next
+    # line. If found, this isn't a single-statement conditional.
+    if (not Match(r'\s*{', endline[endpos:])
+        and not (Match(r'\s*$', endline[endpos:])
+                 and endlinenum < (len(clean_lines.elided) - 1)
+                 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
+      while (endlinenum < len(clean_lines.elided)
+             and ';' not in clean_lines.elided[endlinenum][endpos:]):
+        endlinenum += 1
+        endpos = 0
+      if endlinenum < len(clean_lines.elided):
+        endline = clean_lines.elided[endlinenum]
+        # We allow a mix of whitespace and closing braces (e.g. for one-liner
+        # methods) and a single \ after the semicolon (for macros)
+        endpos = endline.find(';')
+        if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
+          # Semicolon isn't the last character, there's something trailing.
+          # Output a warning if the semicolon is not contained inside
+          # a lambda expression.
+          if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
+                       endline):
+            error(filename, linenum, 'readability/braces', 4,
+                  'If/else bodies with multiple statements require braces')
+        elif endlinenum < len(clean_lines.elided) - 1:
+          # Make sure the next line is dedented
+          next_line = clean_lines.elided[endlinenum + 1]
+          next_indent = GetIndentLevel(next_line)
+          # With ambiguous nested if statements, this will error out on the
+          # if that *doesn't* match the else, regardless of whether it's the
+          # inner one or outer one.
+          if (if_match and Match(r'\s*else\b', next_line)
+              and next_indent != if_indent):
+            error(filename, linenum, 'readability/braces', 4,
+                  'Else clause should be indented at the same level as if. '
+                  'Ambiguous nested if/else chains require braces.')
+          elif next_indent > if_indent:
+            error(filename, linenum, 'readability/braces', 4,
+                  'If/else bodies with multiple statements require braces')
+
+
+def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
+  """Looks for redundant trailing semicolon.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  line = clean_lines.elided[linenum]
+
   # Block bodies should not be followed by a semicolon.  Due to C++11
   # brace initialization, there are more places where semicolons are
   # required than not, so we use a whitelist approach to check these
@@ -3080,21 +4082,31 @@ def CheckBraces(filename, clean_lines, linenum, error):
     # semicolons, while the downside for getting the blacklist wrong
     # would result in compile errors.
     #
-    # In addition to macros, we also don't want to warn on compound
-    # literals.
+    # In addition to macros, we also don't want to warn on
+    #  - Compound literals
+    #  - Lambdas
+    #  - alignas specifier with anonymous structs:
     closing_brace_pos = match.group(1).rfind(')')
     opening_parenthesis = ReverseCloseExpression(
         clean_lines, linenum, closing_brace_pos)
     if opening_parenthesis[2] > -1:
       line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
       macro = Search(r'\b([A-Z_]+)\s*$', line_prefix)
+      func = Match(r'^(.*\])\s*$', line_prefix)
       if ((macro and
            macro.group(1) not in (
                'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
                'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
                'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
+          (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
+          Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
           Search(r'\s+=\s*$', line_prefix)):
         match = None
+    if (match and
+        opening_parenthesis[1] > 1 and
+        Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
+      # Multi-line lambda-expression
+      match = None
 
   else:
     # Try matching cases 2-3.
@@ -3163,6 +4175,29 @@ def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
               'Empty loop bodies should use {} or continue')
 
 
+def FindCheckMacro(line):
+  """Find a replaceable CHECK-like macro.
+
+  Args:
+    line: line to search on.
+  Returns:
+    (macro name, start position), or (None, -1) if no replaceable
+    macro is found.
+  """
+  for macro in _CHECK_MACROS:
+    i = line.find(macro)
+    if i >= 0:
+      # Find opening parenthesis.  Do a regular expression match here
+      # to make sure that we are matching the expected CHECK macro, as
+      # opposed to some other macro that happens to contain the CHECK
+      # substring.
+      matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
+      if not matched:
+        continue
+      return (macro, len(matched.group(1)))
+  return (None, -1)
+
+
 def CheckCheck(filename, clean_lines, linenum, error):
   """Checks the use of CHECK and EXPECT macros.
 
@@ -3175,24 +4210,8 @@ def CheckCheck(filename, clean_lines, linenum, error):
 
   # Decide the set of replacement macros that should be suggested
   lines = clean_lines.elided
-  check_macro = None
-  start_pos = -1
-  for macro in _CHECK_MACROS:
-    i = lines[linenum].find(macro)
-    if i >= 0:
-      check_macro = macro
-
-      # Find opening parenthesis.  Do a regular expression match here
-      # to make sure that we are matching the expected CHECK macro, as
-      # opposed to some other macro that happens to contain the CHECK
-      # substring.
-      matched = Match(r'^(.*\b' + check_macro + r'\s*)\(', lines[linenum])
-      if not matched:
-        continue
-      start_pos = len(matched.group(1))
-      break
-  if not check_macro or start_pos < 0:
-    # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT'
+  (check_macro, start_pos) = FindCheckMacro(lines[linenum])
+  if not check_macro:
     return
 
   # Find end of the boolean expression by matching parentheses
@@ -3200,6 +4219,13 @@ def CheckCheck(filename, clean_lines, linenum, error):
       clean_lines, linenum, start_pos)
   if end_pos < 0:
     return
+
+  # If the check macro is followed by something other than a
+  # semicolon, assume users will log their own custom error messages
+  # and don't suggest any replacements.
+  if not Match(r'\s*;', last_line[end_pos:]):
+    return
+
   if linenum == end_line:
     expression = lines[linenum][start_pos + 1:end_pos - 1]
   else:
@@ -3222,7 +4248,7 @@ def CheckCheck(filename, clean_lines, linenum, error):
       if token == '(':
         # Parenthesized operand
         expression = matched.group(2)
-        (end, _) = FindEndOfExpressionInLine(expression, 0, 1, '(', ')')
+        (end, _) = FindEndOfExpressionInLine(expression, 0, ['('])
         if end < 0:
           return  # Unmatched parenthesis
         lhs += '(' + expression[0:end]
@@ -3357,7 +4383,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
     clean_lines: A CleansedLines instance containing the file.
     linenum: The number of the line to check.
     file_extension: The extension (without the dot) of the filename.
-    nesting_state: A _NestingState instance which maintains information about
+    nesting_state: A NestingState instance which maintains information about
                    the current stack of nested blocks being parsed.
     error: The function to call with any errors found.
   """
@@ -3384,6 +4410,8 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
   # if(match($0, " <<")) complain = 0;
   # if(match(prev, " +for \\(")) complain = 0;
   # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
+  scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$'
+  classinfo = nesting_state.InnermostClass()
   initial_spaces = 0
   cleansed_line = clean_lines.elided[linenum]
   while initial_spaces < len(line) and line[initial_spaces] == ' ':
@@ -3391,9 +4419,12 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
   if line and line[-1].isspace():
     error(filename, linenum, 'whitespace/end_of_line', 4,
           'Line ends in whitespace.  Consider deleting these extra spaces.')
-  # There are certain situations we allow one space, notably for section labels
+  # There are certain situations we allow one space, notably for
+  # section labels, and also lines containing multi-line raw strings.
   elif ((initial_spaces == 1 or initial_spaces == 3) and
-        not Match(r'\s*\w+\s*:\s*$', cleansed_line)):
+        not Match(scope_or_label_pattern, cleansed_line) and
+        not (clean_lines.raw_lines[linenum] != line and
+             Match(r'^\s*""', line))):
     error(filename, linenum, 'whitespace/indent', 3,
           'Weird number of spaces at line-start.  '
           'Are you using a 2-space indent?')
@@ -3441,9 +4472,16 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
 
   # Some more style checks
   CheckBraces(filename, clean_lines, linenum, error)
+  CheckTrailingSemicolon(filename, clean_lines, linenum, error)
   CheckEmptyBlockBody(filename, clean_lines, linenum, error)
   CheckAccess(filename, clean_lines, linenum, nesting_state, error)
   CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
+  CheckOperatorSpacing(filename, clean_lines, linenum, error)
+  CheckParenthesisSpacing(filename, clean_lines, linenum, error)
+  CheckCommaSpacing(filename, clean_lines, linenum, error)
+  CheckBracesSpacing(filename, clean_lines, linenum, error)
+  CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
+  CheckRValueReference(filename, clean_lines, linenum, nesting_state, error)
   CheckCheck(filename, clean_lines, linenum, error)
   CheckAltTokens(filename, clean_lines, linenum, error)
   classinfo = nesting_state.InnermostClass()
@@ -3451,7 +4489,6 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
     CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
 
 
-_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"')
 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
 # Matches the first component of a filename delimited by -s and _s. That is:
 #  _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
@@ -3580,11 +4617,17 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
     error: The function to call with any errors found.
   """
   fileinfo = FileInfo(filename)
-
   line = clean_lines.lines[linenum]
 
   # "include" should use the new style "foo/bar.h" instead of just "bar.h"
-  if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line):
+  # Only do this check if the included header follows google naming
+  # conventions.  If not, assume that it's a 3rd party API that
+  # requires special include conventions.
+  #
+  # We also make an exception for Lua headers, which follow google
+  # naming convention but not the include convention.
+  match = Match(r'#include\s*"([^/]+\.h)"', line)
+  if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
     error(filename, linenum, 'build/include', 4,
           'Include the directory when naming .h files')
 
@@ -3595,12 +4638,17 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
   if match:
     include = match.group(2)
     is_system = (match.group(1) == '<')
-    if include in include_state:
+    duplicate_line = include_state.FindHeader(include)
+    if duplicate_line >= 0:
       error(filename, linenum, 'build/include', 4,
             '"%s" already included at %s:%s' %
-            (include, filename, include_state[include]))
-    else:
-      include_state[include] = linenum
+            (include, filename, duplicate_line))
+    elif (include.endswith('.cc') and
+          os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
+      error(filename, linenum, 'build/include', 4,
+            'Do not include .cc files from other packages')
+    elif not _THIRD_PARTY_HEADERS_PATTERN.match(include):
+      include_state.include_list[-1].append((include, linenum))
 
       # We want to ensure that headers appear in the right order:
       # 1) for foo.cc, foo.h  (preferred location)
@@ -3626,15 +4674,6 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
               'Include "%s" not in alphabetical order' % include)
       include_state.SetLastHeader(canonical_include)
 
-  # Look for any of the stream classes that are part of standard C++.
-  match = _RE_PATTERN_INCLUDE.match(line)
-  if match:
-    include = match.group(2)
-    if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
-      # Many unit tests use cout, so we exempt them.
-      if not _IsTestFilename(filename):
-        error(filename, linenum, 'readability/streams', 3,
-              'Streams are highly discouraged.')
 
 
 def _GetTextInside(text, start_pattern):
@@ -3657,7 +4696,7 @@ def _GetTextInside(text, start_pattern):
     The extracted text.
     None if either the opening string or ending punctuation could not be found.
   """
-  # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably
+  # TODO(unknown): Audit cpplint.py to see what places could be profitably
   # rewritten to use _GetTextInside (and use inferior regexp matching today).
 
   # Give opening punctuations to get the matching close-punctuations.
@@ -3732,7 +4771,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
     linenum: The number of the line to check.
     file_extension: The extension (without the dot) of the filename.
     include_state: An _IncludeState instance in which the headers are inserted.
-    nesting_state: A _NestingState instance which maintains information about
+    nesting_state: A NestingState instance which maintains information about
                    the current stack of nested blocks being parsed.
     error: The function to call with any errors found.
   """
@@ -3749,131 +4788,25 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
 
   # Reset include state across preprocessor directives.  This is meant
   # to silence warnings for conditional includes.
-  if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line):
-    include_state.ResetSection()
+  match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
+  if match:
+    include_state.ResetSection(match.group(1))
 
   # Make Windows paths like Unix.
   fullname = os.path.abspath(filename).replace('\\', '/')
+  
+  # Perform other checks now that we are sure that this is not an include line
+  CheckCasts(filename, clean_lines, linenum, error)
+  CheckGlobalStatic(filename, clean_lines, linenum, error)
+  CheckPrintf(filename, clean_lines, linenum, error)
 
-  # TODO(unknown): figure out if they're using default arguments in fn proto.
-
-  # Check to see if they're using an conversion function cast.
-  # I just try to capture the most common basic types, though there are more.
-  # Parameterless conversion functions, such as bool(), are allowed as they are
-  # probably a member operator declaration or default constructor.
-  match = Search(
-      r'(\bnew\s+)?\b'  # Grab 'new' operator, if it's there
-      r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
-      r'(\([^)].*)', line)
-  if match:
-    matched_new = match.group(1)
-    matched_type = match.group(2)
-    matched_funcptr = match.group(3)
-
-    # gMock methods are defined using some variant of MOCK_METHODx(name, type)
-    # where type may be float(), int(string), etc.  Without context they are
-    # virtually indistinguishable from int(x) casts. Likewise, gMock's
-    # MockCallback takes a template parameter of the form return_type(arg_type),
-    # which looks much like the cast we're trying to detect.
-    #
-    # std::function<> wrapper has a similar problem.
-    #
-    # Return types for function pointers also look like casts if they
-    # don't have an extra space.
-    if (matched_new is None and  # If new operator, then this isn't a cast
-        not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
-             Search(r'\bMockCallback<.*>', line) or
-             Search(r'\bstd::function<.*>', line)) and
-        not (matched_funcptr and
-             Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
-                   matched_funcptr))):
-      # Try a bit harder to catch gmock lines: the only place where
-      # something looks like an old-style cast is where we declare the
-      # return type of the mocked method, and the only time when we
-      # are missing context is if MOCK_METHOD was split across
-      # multiple lines.  The missing MOCK_METHOD is usually one or two
-      # lines back, so scan back one or two lines.
-      #
-      # It's not possible for gmock macros to appear in the first 2
-      # lines, since the class head + section name takes up 2 lines.
-      if (linenum < 2 or
-          not (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
-                     clean_lines.elided[linenum - 1]) or
-               Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
-                     clean_lines.elided[linenum - 2]))):
-        error(filename, linenum, 'readability/casting', 4,
-              'Using deprecated casting style.  '
-              'Use static_cast<%s>(...) instead' %
-              matched_type)
-
-  CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
-                  'static_cast',
-                  r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
-
-  # This doesn't catch all cases. Consider (const char * const)"hello".
-  #
-  # (char *) "foo" should always be a const_cast (reinterpret_cast won't
-  # compile).
-  if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
-                     'const_cast', r'\((char\s?\*+\s?)\)\s*"', error):
-    pass
-  else:
-    # Check pointer casts for other than string constants
-    CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
-                    'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error)
-
-  # In addition, we look for people taking the address of a cast.  This
-  # is dangerous -- casts can assign to temporaries, so the pointer doesn't
-  # point where you think.
-  match = Search(
-      r'(?:&\(([^)]+)\)[\w(])|'
-      r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line)
-  if match and match.group(1) != '*':
-    error(filename, linenum, 'runtime/casting', 4,
-          ('Are you taking an address of a cast?  '
-           'This is dangerous: could be a temp var.  '
-           'Take the address before doing the cast, rather than after'))
-
-  # Create an extended_line, which is the concatenation of the current and
-  # next lines, for more effective checking of code that may span more than one
-  # line.
-  if linenum + 1 < clean_lines.NumLines():
-    extended_line = line + clean_lines.elided[linenum + 1]
-  else:
-    extended_line = line
-
-  # Check for people declaring static/global STL strings at the top level.
-  # This is dangerous because the C++ language does not guarantee that
-  # globals with constructors are initialized before the first access.
-  match = Match(
-      r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
-      line)
-  # Make sure it's not a function.
-  # Function template specialization looks like: "string foo<Type>(...".
-  # Class template definitions look like: "string Foo<Type>::Method(...".
-  #
-  # Also ignore things that look like operators.  These are matched separately
-  # because operator names cross non-word boundaries.  If we change the pattern
-  # above, we would decrease the accuracy of matching identifiers.
-  if (match and
-      not Search(r'\boperator\W', line) and
-      not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))):
-    error(filename, linenum, 'runtime/string', 4,
-          'For a static/global string constant, use a C style string instead: '
-          '"%schar %s[]".' %
-          (match.group(1), match.group(2)))
-
-  if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
-    error(filename, linenum, 'runtime/init', 4,
-          'You seem to be initializing a member variable with itself.')
-
-  if file_extension == 'h':
-    # TODO(unknown): check that 1-arg constructors are explicit.
-    #                How to tell it's a constructor?
-    #                (handled in CheckForNonStandardConstructs for now)
-    # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS
-    #                (level 1 error)
-    pass
+  if file_extension == 'h':
+    # TODO(unknown): check that 1-arg constructors are explicit.
+    #                How to tell it's a constructor?
+    #                (handled in CheckForNonStandardConstructs for now)
+    # TODO(unknown): check that classes declare or disable copy/assign
+    #                (level 1 error)
+    pass
 
   # Check if people are using the verboten C basic types.  The only exception
   # we regularly allow is "unsigned short port" for port.
@@ -3887,23 +4820,6 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
       error(filename, linenum, 'runtime/int', 4,
             'Use int16/int64/etc, rather than the C type %s' % match.group(1))
 
-  # When snprintf is used, the second argument shouldn't be a literal.
-  match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
-  if match and match.group(2) != '0':
-    # If 2nd arg is zero, snprintf is used to calculate size.
-    error(filename, linenum, 'runtime/printf', 3,
-          'If you can, use sizeof(%s) instead of %s as the 2nd arg '
-          'to snprintf.' % (match.group(1), match.group(2)))
-
-  # Check if some verboten C functions are being used.
-  if Search(r'\bsprintf\b', line):
-    error(filename, linenum, 'runtime/printf', 5,
-          'Never use sprintf.  Use snprintf instead.')
-  match = Search(r'\b(strcpy|strcat)\b', line)
-  if match:
-    error(filename, linenum, 'runtime/printf', 4,
-          'Almost always, snprintf is better than %s' % match.group(1))
-
   # Check if some verboten operator overloading is going on
   # TODO(unknown): catch out-of-line unary operator&:
   #   class X {};
@@ -3923,7 +4839,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
   # Check for potential format string bugs like printf(foo).
   # We constrain the pattern not to pick things like DocidForPrintf(foo).
   # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
-  # TODO(sugawarayu): Catch the following case. Need to change the calling
+  # TODO(unknown): Catch the following case. Need to change the calling
   # convention of the whole function to process multiple line to handle it.
   #   printf(
   #       boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
@@ -3988,26 +4904,6 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
             'Do not use variable-length arrays.  Use an appropriately named '
             "('k' followed by CamelCase) compile-time constant for the size.")
 
-  # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or
-  # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing
-  # in the class declaration.
-  match = Match(
-      (r'\s*'
-       r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))'
-       r'\(.*\);$'),
-      line)
-  if match and linenum + 1 < clean_lines.NumLines():
-    next_line = clean_lines.elided[linenum + 1]
-    # We allow some, but not all, declarations of variables to be present
-    # in the statement that defines the class.  The [\w\*,\s]* fragment of
-    # the regular expression below allows users to declare instances of
-    # the class or pointers to instances, but not less common types such
-    # as function pointers or arrays.  It's a tradeoff between allowing
-    # reasonable code and avoiding trying to parse more C++ using regexps.
-    if not Search(r'^\s*}[\w\*,\s]*;', next_line):
-      error(filename, linenum, 'readability/constructors', 3,
-            match.group(1) + ' should be the last thing in the class')
-
   # Check for use of unnamed namespaces in header files.  Registration
   # macros are typically OK, so we allow use of "namespace {" on lines
   # that end with backslashes.
@@ -4019,6 +4915,168 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
           'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
           ' for more information.')
 
+
+def CheckGlobalStatic(filename, clean_lines, linenum, error):
+  """Check for unsafe global or static objects.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Match two lines at a time to support multiline declarations
+  if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line):
+    line += clean_lines.elided[linenum + 1].strip()
+
+  # Check for people declaring static/global STL strings at the top level.
+  # This is dangerous because the C++ language does not guarantee that
+  # globals with constructors are initialized before the first access.
+  match = Match(
+      r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
+      line)
+
+  # Remove false positives:
+  # - String pointers (as opposed to values).
+  #    string *pointer
+  #    const string *pointer
+  #    string const *pointer
+  #    string *const pointer
+  #
+  # - Functions and template specializations.
+  #    string Function<Type>(...
+  #    string Class<Type>::Method(...
+  #
+  # - Operators.  These are matched separately because operator names
+  #   cross non-word boundaries, and trying to match both operators
+  #   and functions at the same time would decrease accuracy of
+  #   matching identifiers.
+  #    string Class::operator*()
+  if (match and
+      not Search(r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line) and
+      not Search(r'\boperator\W', line) and
+      not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(3))):
+    error(filename, linenum, 'runtime/string', 4,
+          'For a static/global string constant, use a C style string instead: '
+          '"%schar %s[]".' %
+          (match.group(1), match.group(2)))
+
+  if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
+    error(filename, linenum, 'runtime/init', 4,
+          'You seem to be initializing a member variable with itself.')
+
+
+def CheckPrintf(filename, clean_lines, linenum, error):
+  """Check for printf related issues.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # When snprintf is used, the second argument shouldn't be a literal.
+  match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
+  if match and match.group(2) != '0':
+    # If 2nd arg is zero, snprintf is used to calculate size.
+    error(filename, linenum, 'runtime/printf', 3,
+          'If you can, use sizeof(%s) instead of %s as the 2nd arg '
+          'to snprintf.' % (match.group(1), match.group(2)))
+
+  # Check if some verboten C functions are being used.
+  if Search(r'\bsprintf\s*\(', line):
+    error(filename, linenum, 'runtime/printf', 5,
+          'Never use sprintf. Use snprintf instead.')
+  match = Search(r'\b(strcpy|strcat)\s*\(', line)
+  if match:
+    error(filename, linenum, 'runtime/printf', 4,
+          'Almost always, snprintf is better than %s' % match.group(1))
+
+
+def IsDerivedFunction(clean_lines, linenum):
+  """Check if current line contains an inherited function.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if current line contains a function with "override"
+    virt-specifier.
+  """
+  # Scan back a few lines for start of current function
+  for i in xrange(linenum, max(-1, linenum - 10), -1):
+    match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
+    if match:
+      # Look for "override" after the matching closing parenthesis
+      line, _, closing_paren = CloseExpression(
+          clean_lines, i, len(match.group(1)))
+      return (closing_paren >= 0 and
+              Search(r'\boverride\b', line[closing_paren:]))
+  return False
+
+
+def IsOutOfLineMethodDefinition(clean_lines, linenum):
+  """Check if current line contains an out-of-line method definition.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if current line contains an out-of-line method definition.
+  """
+  # Scan back a few lines for start of current function
+  for i in xrange(linenum, max(-1, linenum - 10), -1):
+    if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
+      return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
+  return False
+
+
+def IsInitializerList(clean_lines, linenum):
+  """Check if current line is inside constructor initializer list.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if current line appears to be inside constructor initializer
+    list, False otherwise.
+  """
+  for i in xrange(linenum, 1, -1):
+    line = clean_lines.elided[i]
+    if i == linenum:
+      remove_function_body = Match(r'^(.*)\{\s*$', line)
+      if remove_function_body:
+        line = remove_function_body.group(1)
+
+    if Search(r'\s:\s*\w+[({]', line):
+      # A lone colon tend to indicate the start of a constructor
+      # initializer list.  It could also be a ternary operator, which
+      # also tend to appear in constructor initializer lists as
+      # opposed to parameter lists.
+      return True
+    if Search(r'\}\s*,\s*$', line):
+      # A closing brace followed by a comma is probably the end of a
+      # brace-initialized member in constructor initializer list.
+      return True
+    if Search(r'[{};]\s*$', line):
+      # Found one of the following:
+      # - A closing brace or semicolon, probably the end of the previous
+      #   function.
+      # - An opening brace, probably the start of current class or namespace.
+      #
+      # Current line is probably not inside an initializer list since
+      # we saw one of those things without seeing the starting colon.
+      return False
+
+  # Got to the beginning of the file without seeing the start of
+  # constructor initializer list.
+  return False
+
+
 def CheckForNonConstReference(filename, clean_lines, linenum,
                               nesting_state, error):
   """Check for non-const references.
@@ -4030,7 +5088,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
     filename: The name of the current file.
     clean_lines: A CleansedLines instance containing the file.
     linenum: The number of the line to check.
-    nesting_state: A _NestingState instance which maintains information about
+    nesting_state: A NestingState instance which maintains information about
                    the current stack of nested blocks being parsed.
     error: The function to call with any errors found.
   """
@@ -4039,6 +5097,17 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
   if '&' not in line:
     return
 
+  # If a function is inherited, current function doesn't have much of
+  # a choice, so any non-const references should not be blamed on
+  # derived function.
+  if IsDerivedFunction(clean_lines, linenum):
+    return
+
+  # Don't warn on out-of-line method definitions, as we would warn on the
+  # in-line declaration, if it isn't marked with 'override'.
+  if IsOutOfLineMethodDefinition(clean_lines, linenum):
+    return
+
   # Long type names may be broken across multiple lines, usually in one
   # of these forms:
   #   LongType
@@ -4087,19 +5156,35 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
   #   inside declarators: reference parameter
   # We will exclude the first two cases by checking that we are not inside a
   # function body, including one that was just introduced by a trailing '{'.
-  # TODO(unknwon): Doesn't account for preprocessor directives.
   # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
-  check_params = False
-  if not nesting_state.stack:
-    check_params = True  # top level
-  elif (isinstance(nesting_state.stack[-1], _ClassInfo) or
-        isinstance(nesting_state.stack[-1], _NamespaceInfo)):
-    check_params = True  # within class or namespace
-  elif Match(r'.*{\s*$', line):
-    if (len(nesting_state.stack) == 1 or
-        isinstance(nesting_state.stack[-2], _ClassInfo) or
-        isinstance(nesting_state.stack[-2], _NamespaceInfo)):
-      check_params = True  # just opened global/class/namespace block
+  if (nesting_state.previous_stack_top and
+      not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
+           isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
+    # Not at toplevel, not within a class, and not within a namespace
+    return
+
+  # Avoid initializer lists.  We only need to scan back from the
+  # current line for something that starts with ':'.
+  #
+  # We don't need to check the current line, since the '&' would
+  # appear inside the second set of parentheses on the current line as
+  # opposed to the first set.
+  if linenum > 0:
+    for i in xrange(linenum - 1, max(0, linenum - 10), -1):
+      previous_line = clean_lines.elided[i]
+      if not Search(r'[),]\s*$', previous_line):
+        break
+      if Match(r'^\s*:\s+\S', previous_line):
+        return
+
+  # Avoid preprocessors
+  if Search(r'\\\s*$', line):
+    return
+
+  # Avoid constructor initializer lists
+  if IsInitializerList(clean_lines, linenum):
+    return
+
   # We allow non-const references in a few standard places, like functions
   # called "swap()" or iostream operators like "<<" or ">>".  Do not check
   # those function parameters.
@@ -4111,7 +5196,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
                            r'static_assert|COMPILE_ASSERT'
                            r')\s*\(')
   if Search(whitelisted_functions, line):
-    check_params = False
+    return
   elif not Search(r'\S+\([^)]*$', line):
     # Don't see a whitelisted function on this line.  Actually we
     # didn't see any function name on this line, so this is likely a
@@ -4119,28 +5204,143 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
     for i in xrange(2):
       if (linenum > i and
           Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
-        check_params = False
-        break
+        return
+
+  decls = ReplaceAll(r'{[^}]*}', ' ', line)  # exclude function body
+  for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
+    if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
+      error(filename, linenum, 'runtime/references', 2,
+            'Is this a non-const reference? '
+            'If so, make const or use a pointer: ' +
+            ReplaceAll(' *<', '<', parameter))
+
+
+def CheckCasts(filename, clean_lines, linenum, error):
+  """Various cast related checks.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
 
-  if check_params:
-    decls = ReplaceAll(r'{[^}]*}', ' ', line)  # exclude function body
-    for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
-      if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
-        error(filename, linenum, 'runtime/references', 2,
-              'Is this a non-const reference? '
-              'If so, make const or use a pointer: ' +
-              ReplaceAll(' *<', '<', parameter))
+  # Check to see if they're using an conversion function cast.
+  # I just try to capture the most common basic types, though there are more.
+  # Parameterless conversion functions, such as bool(), are allowed as they are
+  # probably a member operator declaration or default constructor.
+  match = Search(
+      r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b'
+      r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
+      r'(\([^)].*)', line)
+  expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
+  if match and not expecting_function:
+    matched_type = match.group(2)
+
+    # matched_new_or_template is used to silence two false positives:
+    # - New operators
+    # - Template arguments with function types
+    #
+    # For template arguments, we match on types immediately following
+    # an opening bracket without any spaces.  This is a fast way to
+    # silence the common case where the function type is the first
+    # template argument.  False negative with less-than comparison is
+    # avoided because those operators are usually followed by a space.
+    #
+    #   function<double(double)>   // bracket + no space = false positive
+    #   value < double(42)         // bracket + space = true positive
+    matched_new_or_template = match.group(1)
+
+    # Avoid arrays by looking for brackets that come after the closing
+    # parenthesis.
+    if Match(r'\([^()]+\)\s*\[', match.group(3)):
+      return
+
+    # Other things to ignore:
+    # - Function pointers
+    # - Casts to pointer types
+    # - Placement new
+    # - Alias declarations
+    matched_funcptr = match.group(3)
+    if (matched_new_or_template is None and
+        not (matched_funcptr and
+             (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
+                    matched_funcptr) or
+              matched_funcptr.startswith('(*)'))) and
+        not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
+        not Search(r'new\(\S+\)\s*' + matched_type, line)):
+      error(filename, linenum, 'readability/casting', 4,
+            'Using deprecated casting style.  '
+            'Use static_cast<%s>(...) instead' %
+            matched_type)
+
+  if not expecting_function:
+    CheckCStyleCast(filename, clean_lines, linenum, 'static_cast',
+                    r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
+
+  # This doesn't catch all cases. Consider (const char * const)"hello".
+  #
+  # (char *) "foo" should always be a const_cast (reinterpret_cast won't
+  # compile).
+  if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast',
+                     r'\((char\s?\*+\s?)\)\s*"', error):
+    pass
+  else:
+    # Check pointer casts for other than string constants
+    CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast',
+                    r'\((\w+\s?\*+\s?)\)', error)
+
+  # In addition, we look for people taking the address of a cast.  This
+  # is dangerous -- casts can assign to temporaries, so the pointer doesn't
+  # point where you think.
+  #
+  # Some non-identifier character is required before the '&' for the
+  # expression to be recognized as a cast.  These are casts:
+  #   expression = &static_cast<int*>(temporary());
+  #   function(&(int*)(temporary()));
+  #
+  # This is not a cast:
+  #   reference_type&(int* function_param);
+  match = Search(
+      r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
+      r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
+  if match:
+    # Try a better error message when the & is bound to something
+    # dereferenced by the casted pointer, as opposed to the casted
+    # pointer itself.
+    parenthesis_error = False
+    match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
+    if match:
+      _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
+      if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
+        _, y2, x2 = CloseExpression(clean_lines, y1, x1)
+        if x2 >= 0:
+          extended_line = clean_lines.elided[y2][x2:]
+          if y2 < clean_lines.NumLines() - 1:
+            extended_line += clean_lines.elided[y2 + 1]
+          if Match(r'\s*(?:->|\[)', extended_line):
+            parenthesis_error = True
+
+    if parenthesis_error:
+      error(filename, linenum, 'readability/casting', 4,
+            ('Are you taking an address of something dereferenced '
+             'from a cast?  Wrapping the dereferenced expression in '
+             'parentheses will make the binding more obvious'))
+    else:
+      error(filename, linenum, 'runtime/casting', 4,
+            ('Are you taking an address of a cast?  '
+             'This is dangerous: could be a temp var.  '
+             'Take the address before doing the cast, rather than after'))
 
 
-def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
-                    error):
+def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
   """Checks for a C-style cast by looking for the pattern.
 
   Args:
     filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
     linenum: The number of the line to check.
-    line: The line of code to check.
-    raw_line: The raw line of code to check, with comments.
     cast_type: The string for the C++ cast to recommend.  This is either
       reinterpret_cast, static_cast, or const_cast, depending.
     pattern: The regular expression used to find C-style casts.
@@ -4150,18 +5350,26 @@ def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
     True if an error was emitted.
     False otherwise.
   """
+  line = clean_lines.elided[linenum]
   match = Search(pattern, line)
   if not match:
     return False
 
-  # Exclude lines with sizeof, since sizeof looks like a cast.
-  sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1])
-  if sizeof_match:
+  # Exclude lines with keywords that tend to look like casts
+  context = line[0:match.start(1) - 1]
+  if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
+    return False
+
+  # Try expanding current context to see if we one level of
+  # parentheses inside a macro.
+  if linenum > 0:
+    for i in xrange(linenum - 1, max(0, linenum - 5), -1):
+      context = clean_lines.elided[i] + context
+  if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
     return False
 
   # operator++(int) and operator--(int)
-  if (line[0:match.start(1) - 1].endswith(' operator++') or
-      line[0:match.start(1) - 1].endswith(' operator--')):
+  if context.endswith(' operator++') or context.endswith(' operator--'):
     return False
 
   # A single unnamed argument for a function tends to look like old
@@ -4178,6 +5386,7 @@ def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
   #   ExceptionMember(int) throw (...);
   #   ExceptionMember(int) throw (...) {
   #   PureVirtual(int) = 0;
+  #   [](int) -> bool {
   #
   # These are functions of some sort, where the compiler would be fine
   # if they had named parameters, but people often omit those
@@ -4185,10 +5394,12 @@ def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
   #   (FunctionPointer)(int);
   #   (FunctionPointer)(int) = value;
   #   Function((function_pointer_arg)(int))
+  #   Function((function_pointer_arg)(int), int param)
   #   <TemplateArgument(int)>;
   #   <(FunctionPointerTemplateArgument)(int)>;
   remainder = line[match.end(0):]
-  if Match(r'^\s*(?:;|const\b|throw\b|=|>|\{|\))', remainder):
+  if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
+           remainder):
     # Looks like an unnamed parameter.
 
     # Don't warn on any kind of template arguments.
@@ -4210,6 +5421,7 @@ def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
 
     # Don't warn if the parameter is named with block comments, e.g.:
     #  Function(int /*unused_param*/);
+    raw_line = clean_lines.raw_lines[linenum]
     if '/*' in raw_line:
       return False
 
@@ -4226,6 +5438,28 @@ def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
   return True
 
 
+def ExpectingFunctionArgs(clean_lines, linenum):
+  """Checks whether where function type arguments are expected.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+
+  Returns:
+    True if the line at 'linenum' is inside something that expects arguments
+    of function types.
+  """
+  line = clean_lines.elided[linenum]
+  return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
+          (linenum >= 2 and
+           (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
+                  clean_lines.elided[linenum - 1]) or
+            Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
+                  clean_lines.elided[linenum - 2]) or
+            Search(r'\bstd::m?function\s*\<\s*$',
+                   clean_lines.elided[linenum - 1]))))
+
+
 _HEADERS_CONTAINING_TEMPLATES = (
     ('<deque>', ('deque',)),
     ('<functional>', ('unary_function', 'binary_function',
@@ -4253,6 +5487,7 @@ _HEADERS_CONTAINING_TEMPLATES = (
     ('<set>', ('set', 'multiset',)),
     ('<stack>', ('stack',)),
     ('<string>', ('char_traits', 'basic_string',)),
+    ('<tuple>', ('tuple',)),
     ('<utility>', ('pair',)),
     ('<vector>', ('vector',)),
 
@@ -4339,16 +5574,16 @@ def FilesBelongToSameModule(filename_cc, filename_h):
   return files_belong_to_same_module, common_path
 
 
-def UpdateIncludeState(filename, include_state, io=codecs):
-  """Fill up the include_state with new includes found from the file.
+def UpdateIncludeState(filename, include_dict, io=codecs):
+  """Fill up the include_dict with new includes found from the file.
 
   Args:
     filename: the name of the header to read.
-    include_state: an _IncludeState instance in which the headers are inserted.
+    include_dict: a dictionary in which the headers are inserted.
     io: The io factory to use to read the file. Provided for testability.
 
   Returns:
-    True if a header was succesfully added. False otherwise.
+    True if a header was successfully added. False otherwise.
   """
   headerfile = None
   try:
@@ -4362,9 +5597,7 @@ def UpdateIncludeState(filename, include_state, io=codecs):
     match = _RE_PATTERN_INCLUDE.search(clean_line)
     if match:
       include = match.group(2)
-      # The value formatting is cute, but not really used right now.
-      # What matters here is that the key is in include_state.
-      include_state.setdefault(include, '%s:%d' % (filename, linenum))
+      include_dict.setdefault(include, linenum)
   return True
 
 
@@ -4417,10 +5650,11 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
 
   # The policy is that if you #include something in foo.h you don't need to
   # include it again in foo.cc. Here, we will look at possible includes.
-  # Let's copy the include_state so it is only messed up within this function.
-  include_state = include_state.copy()
+  # Let's flatten the include_state include_list and copy it into a dictionary.
+  include_dict = dict([item for sublist in include_state.include_list
+                       for item in sublist])
 
-  # Did we find the header for this file (if any) and succesfully load it?
+  # Did we find the header for this file (if any) and successfully load it?
   header_found = False
 
   # Use the absolute path so that matching works properly.
@@ -4435,13 +5669,13 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
   # instead of 'foo_flymake.h'
   abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
 
-  # include_state is modified during iteration, so we iterate over a copy of
+  # include_dict is modified during iteration, so we iterate over a copy of
   # the keys.
-  header_keys = include_state.keys()
+  header_keys = include_dict.keys()
   for header in header_keys:
     (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
     fullpath = common_path + header
-    if same_module and UpdateIncludeState(fullpath, include_state, io):
+    if same_module and UpdateIncludeState(fullpath, include_dict, io):
       header_found = True
 
   # If we can't find the header file for a .cc, assume it's because we don't
@@ -4455,7 +5689,7 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
   # All the lines have been processed, report the errors found.
   for required_header_unstripped in required:
     template = required[required_header_unstripped][1]
-    if required_header_unstripped.strip('<>"') not in include_state:
+    if required_header_unstripped.strip('<>"') not in include_dict:
       error(filename, required[required_header_unstripped][0],
             'build/include_what_you_use', 4,
             'Add #include ' + required_header_unstripped + ' for ' + template)
@@ -4467,7 +5701,7 @@ _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<')
 def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
   """Check that make_pair's template arguments are deduced.
 
-  G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are
+  G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are
   specified explicitly, and such use isn't intended in any case.
 
   Args:
@@ -4485,6 +5719,190 @@ def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
           ' OR use pair directly OR if appropriate, construct a pair directly')
 
 
+def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error):
+  """Check that default lambda captures are not used.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # A lambda introducer specifies a default capture if it starts with "[="
+  # or if it starts with "[&" _not_ followed by an identifier.
+  match = Match(r'^(.*)\[\s*(?:=|&[^\w])', line)
+  if match:
+    # Found a potential error, check what comes after the lambda-introducer.
+    # If it's not open parenthesis (for lambda-declarator) or open brace
+    # (for compound-statement), it's not a lambda.
+    line, _, pos = CloseExpression(clean_lines, linenum, len(match.group(1)))
+    if pos >= 0 and Match(r'^\s*[{(]', line[pos:]):
+      error(filename, linenum, 'build/c++11',
+            4,  # 4 = high confidence
+            'Default lambda captures are an unapproved C++ feature.')
+
+
+def CheckRedundantVirtual(filename, clean_lines, linenum, error):
+  """Check if line contains a redundant "virtual" function-specifier.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  # Look for "virtual" on current line.
+  line = clean_lines.elided[linenum]
+  virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line)
+  if not virtual: return
+
+  # Ignore "virtual" keywords that are near access-specifiers.  These
+  # are only used in class base-specifier and do not apply to member
+  # functions.
+  if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or
+      Match(r'^\s+(public|protected|private)\b', virtual.group(3))):
+    return
+
+  # Ignore the "virtual" keyword from virtual base classes.  Usually
+  # there is a column on the same line in these cases (virtual base
+  # classes are rare in google3 because multiple inheritance is rare).
+  if Match(r'^.*[^:]:[^:].*$', line): return
+
+  # Look for the next opening parenthesis.  This is the start of the
+  # parameter list (possibly on the next line shortly after virtual).
+  # TODO(unknown): doesn't work if there are virtual functions with
+  # decltype() or other things that use parentheses, but csearch suggests
+  # that this is rare.
+  end_col = -1
+  end_line = -1
+  start_col = len(virtual.group(2))
+  for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
+    line = clean_lines.elided[start_line][start_col:]
+    parameter_list = Match(r'^([^(]*)\(', line)
+    if parameter_list:
+      # Match parentheses to find the end of the parameter list
+      (_, end_line, end_col) = CloseExpression(
+          clean_lines, start_line, start_col + len(parameter_list.group(1)))
+      break
+    start_col = 0
+
+  if end_col < 0:
+    return  # Couldn't find end of parameter list, give up
+
+  # Look for "override" or "final" after the parameter list
+  # (possibly on the next few lines).
+  for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
+    line = clean_lines.elided[i][end_col:]
+    match = Search(r'\b(override|final)\b', line)
+    if match:
+      error(filename, linenum, 'readability/inheritance', 4,
+            ('"virtual" is redundant since function is '
+             'already declared as "%s"' % match.group(1)))
+
+    # Set end_col to check whole lines after we are done with the
+    # first line.
+    end_col = 0
+    if Search(r'[^\w]\s*$', line):
+      break
+
+
+def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
+  """Check if line contains a redundant "override" or "final" virt-specifier.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  # Look for closing parenthesis nearby.  We need one to confirm where
+  # the declarator ends and where the virt-specifier starts to avoid
+  # false positives.
+  line = clean_lines.elided[linenum]
+  declarator_end = line.rfind(')')
+  if declarator_end >= 0:
+    fragment = line[declarator_end:]
+  else:
+    if linenum > 1 and clean_lines.elided[linenum - 1].rfind(')') >= 0:
+      fragment = line
+    else:
+      return
+
+  # Check that at most one of "override" or "final" is present, not both
+  if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment):
+    error(filename, linenum, 'readability/inheritance', 4,
+          ('"override" is redundant since function is '
+           'already declared as "final"'))
+
+
+
+
+# Returns true if we are at a new block, and it is directly
+# inside of a namespace.
+def IsBlockInNameSpace(nesting_state, is_forward_declaration):
+  """Checks that the new block is directly in a namespace.
+
+  Args:
+    nesting_state: The _NestingState object that contains info about our state.
+    is_forward_declaration: If the class is a forward declared class.
+  Returns:
+    Whether or not the new block is directly in a namespace.
+  """
+  if is_forward_declaration:
+    if len(nesting_state.stack) >= 1 and (
+        isinstance(nesting_state.stack[-1], _NamespaceInfo)):
+      return True
+    else:
+      return False
+
+  return (len(nesting_state.stack) > 1 and
+          nesting_state.stack[-1].check_namespace_indentation and
+          isinstance(nesting_state.stack[-2], _NamespaceInfo))
+
+
+def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
+                                    raw_lines_no_comments, linenum):
+  """This method determines if we should apply our namespace indentation check.
+
+  Args:
+    nesting_state: The current nesting state.
+    is_namespace_indent_item: If we just put a new class on the stack, True.
+      If the top of the stack is not a class, or we did not recently
+      add the class, False.
+    raw_lines_no_comments: The lines without the comments.
+    linenum: The current line number we are processing.
+
+  Returns:
+    True if we should apply our namespace indentation check. Currently, it
+    only works for classes and namespaces inside of a namespace.
+  """
+
+  is_forward_declaration = IsForwardClassDeclaration(raw_lines_no_comments,
+                                                     linenum)
+
+  if not (is_namespace_indent_item or is_forward_declaration):
+    return False
+
+  # If we are in a macro, we do not want to check the namespace indentation.
+  if IsMacroDefinition(raw_lines_no_comments, linenum):
+    return False
+
+  return IsBlockInNameSpace(nesting_state, is_forward_declaration)
+
+
+# Call this method if the line is directly inside of a namespace.
+# If the line above is blank (excluding comments) or the start of
+# an inner namespace, it cannot be indented.
+def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum,
+                                    error):
+  line = raw_lines_no_comments[linenum]
+  if Match(r'^\s+', line):
+    error(filename, linenum, 'runtime/indentation_namespace', 4,
+          'Do not indent within a namespace')
+
+
 def ProcessLine(filename, file_extension, clean_lines, line,
                 include_state, function_state, nesting_state, error,
                 extra_check_functions=[]):
@@ -4498,7 +5916,7 @@ def ProcessLine(filename, file_extension, clean_lines, line,
     line: Number of line being processed.
     include_state: An _IncludeState instance in which the headers are inserted.
     function_state: A _FunctionState instance which counts function lines, etc.
-    nesting_state: A _NestingState instance which maintains information about
+    nesting_state: A NestingState instance which maintains information about
                    the current stack of nested blocks being parsed.
     error: A callable to which errors are reported, which takes 4 arguments:
            filename, line number, error level, and message
@@ -4509,8 +5927,9 @@ def ProcessLine(filename, file_extension, clean_lines, line,
   raw_lines = clean_lines.raw_lines
   ParseNolintSuppressions(filename, raw_lines[line], line, error)
   nesting_state.Update(filename, clean_lines, line, error)
-  if nesting_state.stack and nesting_state.stack[-1].inline_asm != _NO_ASM:
-    return
+  CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
+                               error)
+  if nesting_state.InAsmBlock(): return
   CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
   CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
   CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
@@ -4523,9 +5942,58 @@ def ProcessLine(filename, file_extension, clean_lines, line,
   CheckPosixThreading(filename, clean_lines, line, error)
   CheckInvalidIncrement(filename, clean_lines, line, error)
   CheckMakePairUsesDeduction(filename, clean_lines, line, error)
+  CheckDefaultLambdaCaptures(filename, clean_lines, line, error)
+  CheckRedundantVirtual(filename, clean_lines, line, error)
+  CheckRedundantOverrideOrFinal(filename, clean_lines, line, error)
   for check_fn in extra_check_functions:
     check_fn(filename, clean_lines, line, error)
 
+def FlagCxx11Features(filename, clean_lines, linenum, error):
+  """Flag those c++11 features that we only allow in certain places.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Flag unapproved C++11 headers.
+  include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
+  if include and include.group(1) in ('cfenv',
+                                      'condition_variable',
+                                      'fenv.h',
+                                      'future',
+                                      'mutex',
+                                      'thread',
+                                      'chrono',
+                                      'ratio',
+                                      'regex',
+                                      'system_error',
+                                     ):
+    error(filename, linenum, 'build/c++11', 5,
+          ('<%s> is an unapproved C++11 header.') % include.group(1))
+
+  # The only place where we need to worry about C++11 keywords and library
+  # features in preprocessor directives is in macro definitions.
+  if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return
+
+  # These are classes and free functions.  The classes are always
+  # mentioned as std::*, but we only catch the free functions if
+  # they're not found by ADL.  They're alphabetical by header.
+  for top_name in (
+      # type_traits
+      'alignment_of',
+      'aligned_union',
+      ):
+    if Search(r'\bstd::%s\b' % top_name, line):
+      error(filename, linenum, 'build/c++11', 5,
+            ('std::%s is an unapproved C++11 class or function.  Send c-style '
+             'an example of where it would make your code more readable, and '
+             'they may let you use it.') % top_name)
+
+
 def ProcessFileData(filename, file_extension, lines, error,
                     extra_check_functions=[]):
   """Performs lint checks and reports any errors to the given error function.
@@ -4546,24 +6014,30 @@ def ProcessFileData(filename, file_extension, lines, error,
 
   include_state = _IncludeState()
   function_state = _FunctionState()
-  nesting_state = _NestingState()
+  nesting_state = NestingState()
 
   ResetNolintSuppressions()
 
   CheckForCopyright(filename, lines, error)
 
-  if file_extension == 'h':
-    CheckForHeaderGuard(filename, lines, error)
-
   RemoveMultiLineComments(filename, lines, error)
   clean_lines = CleansedLines(lines)
+
+  if file_extension == 'h':
+    CheckForHeaderGuard(filename, clean_lines, error)
+
   for line in xrange(clean_lines.NumLines()):
     ProcessLine(filename, file_extension, clean_lines, line,
                 include_state, function_state, nesting_state, error,
                 extra_check_functions)
+    FlagCxx11Features(filename, clean_lines, line, error)
   nesting_state.CheckCompletedBlocks(filename, error)
 
   CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
+  
+  # Check that the .cc file has included its header if it exists.
+  if file_extension == 'cc':
+    CheckHeaderFileIncluded(filename, include_state, error)
 
   # We check here rather than inside ProcessLine so that we see raw
   # lines rather than "cleaned" lines.
@@ -4571,6 +6045,82 @@ def ProcessFileData(filename, file_extension, lines, error,
 
   CheckForNewlineAtEOF(filename, lines, error)
 
+def ProcessConfigOverrides(filename):
+  """ Loads the configuration files and processes the config overrides.
+
+  Args:
+    filename: The name of the file being processed by the linter.
+
+  Returns:
+    False if the current |filename| should not be processed further.
+  """
+
+  abs_filename = os.path.abspath(filename)
+  cfg_filters = []
+  keep_looking = True
+  while keep_looking:
+    abs_path, base_name = os.path.split(abs_filename)
+    if not base_name:
+      break  # Reached the root directory.
+
+    cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
+    abs_filename = abs_path
+    if not os.path.isfile(cfg_file):
+      continue
+
+    try:
+      with open(cfg_file) as file_handle:
+        for line in file_handle:
+          line, _, _ = line.partition('#')  # Remove comments.
+          if not line.strip():
+            continue
+
+          name, _, val = line.partition('=')
+          name = name.strip()
+          val = val.strip()
+          if name == 'set noparent':
+            keep_looking = False
+          elif name == 'filter':
+            cfg_filters.append(val)
+          elif name == 'exclude_files':
+            # When matching exclude_files pattern, use the base_name of
+            # the current file name or the directory name we are processing.
+            # For example, if we are checking for lint errors in /foo/bar/baz.cc
+            # and we found the .cfg file at /foo/CPPLINT.cfg, then the config
+            # file's "exclude_files" filter is meant to be checked against "bar"
+            # and not "baz" nor "bar/baz.cc".
+            if base_name:
+              pattern = re.compile(val)
+              if pattern.match(base_name):
+                sys.stderr.write('Ignoring "%s": file excluded by "%s". '
+                                 'File path component "%s" matches '
+                                 'pattern "%s"\n' %
+                                 (filename, cfg_file, base_name, val))
+                return False
+          elif name == 'linelength':
+            global _line_length
+            try:
+                _line_length = int(val)
+            except ValueError:
+                sys.stderr.write('Line length must be numeric.')
+          else:
+            sys.stderr.write(
+                'Invalid configuration option (%s) in file %s\n' %
+                (name, cfg_file))
+
+    except IOError:
+      sys.stderr.write(
+          "Skipping config file '%s': Can't open for reading\n" % cfg_file)
+      keep_looking = False
+
+  # Apply all the accumulated filters in reverse order (top-level directory
+  # config options having the least priority).
+  for filter in reversed(cfg_filters):
+     _AddFilters(filter)
+
+  return True
+
+
 def ProcessFile(filename, vlevel, extra_check_functions=[]):
   """Does google-lint on a single file.
 
@@ -4586,7 +6136,14 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]):
   """
 
   _SetVerboseLevel(vlevel)
+  _BackupFilters()
+
+  if not ProcessConfigOverrides(filename):
+    _RestoreFilters()
+    return
 
+  lf_lines = []
+  crlf_lines = []
   try:
     # Support the UNIX convention of using "-" for stdin.  Note that
     # we are not opening the file with universal newline support
@@ -4594,10 +6151,7 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]):
     # contain trailing '\r' characters if we are reading a file that
     # has CRLF endings.
     # If after the split a trailing '\r' is present, it is removed
-    # below. If it is not expected to be present (i.e. os.linesep !=
-    # '\r\n' as in Windows), a warning is issued below if this file
-    # is processed.
-
+    # below.
     if filename == '-':
       lines = codecs.StreamReaderWriter(sys.stdin,
                                         codecs.getreader('utf8'),
@@ -4606,16 +6160,19 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]):
     else:
       lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
 
-    carriage_return_found = False
     # Remove trailing '\r'.
-    for linenum in range(len(lines)):
+    # The -1 accounts for the extra trailing blank line we get from split()
+    for linenum in range(len(lines) - 1):
       if lines[linenum].endswith('\r'):
         lines[linenum] = lines[linenum].rstrip('\r')
-        carriage_return_found = True
+        crlf_lines.append(linenum + 1)
+      else:
+        lf_lines.append(linenum + 1)
 
   except IOError:
     sys.stderr.write(
         "Skipping input '%s': Can't open for reading\n" % filename)
+    _RestoreFilters()
     return
 
   # Note, if no dot is found, this will give the entire filename as the ext.
@@ -4629,14 +6186,27 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]):
   else:
     ProcessFileData(filename, file_extension, lines, Error,
                     extra_check_functions)
-    if carriage_return_found and os.linesep != '\r\n':
-      # Use 0 for linenum since outputting only one error for potentially
-      # several lines.
-      Error(filename, 0, 'whitespace/newline', 1,
-            'One or more unexpected \\r (^M) found;'
-            'better to use only a \\n')
+
+    # If end-of-line sequences are a mix of LF and CR-LF, issue
+    # warnings on the lines with CR.
+    #
+    # Don't issue any warnings if all lines are uniformly LF or CR-LF,
+    # since critique can handle these just fine, and the style guide
+    # doesn't dictate a particular end of line sequence.
+    #
+    # We can't depend on os.linesep to determine what the desired
+    # end-of-line sequence should be, since that will return the
+    # server-side end-of-line sequence.
+    if lf_lines and crlf_lines:
+      # Warn on every line with CR.  An alternative approach might be to
+      # check whether the file is mostly CRLF or just LF, and warn on the
+      # minority, we bias toward LF here since most tools prefer LF.
+      for linenum in crlf_lines:
+        Error(filename, linenum, 'whitespace/newline', 1,
+              'Unexpected \\r (^M) found; better to use only \\n')
 
   sys.stderr.write('Done processing %s\n' % filename)
+  _RestoreFilters()
 
 
 def PrintUsage(message):
diff --git a/examples/async_pi_estimate/addon.cc b/examples/async_pi_estimate/addon.cc
index 6ad45ef..f496378 100644
--- a/examples/async_pi_estimate/addon.cc
+++ b/examples/async_pi_estimate/addon.cc
@@ -1,15 +1,14 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
-#include <node.h>
 #include <nan.h>
-#include "./sync.h"
-#include "./async.h"
+#include "sync.h"   // NOLINT(build/include)
+#include "async.h"  // NOLINT(build/include)
 
 using v8::FunctionTemplate;
 using v8::Handle;
diff --git a/examples/async_pi_estimate/addon.js b/examples/async_pi_estimate/addon.js
index abd3e00..08d666e 100644
--- a/examples/async_pi_estimate/addon.js
+++ b/examples/async_pi_estimate/addon.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 var addon = require('./build/Release/addon');
 var calculations = process.argv[2] || 100000000;
 
diff --git a/examples/async_pi_estimate/async.cc b/examples/async_pi_estimate/async.cc
index 63dc80d..4d96452 100644
--- a/examples/async_pi_estimate/async.cc
+++ b/examples/async_pi_estimate/async.cc
@@ -1,15 +1,14 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
-#include <node.h>
 #include <nan.h>
-#include "./pi_est.h"
-#include "./async.h"
+#include "pi_est.h"  // NOLINT(build/include)
+#include "async.h"  // NOLINT(build/include)
 
 using v8::Function;
 using v8::Local;
diff --git a/examples/async_pi_estimate/async.h b/examples/async_pi_estimate/async.h
index 055b51f..82a596c 100644
--- a/examples/async_pi_estimate/async.h
+++ b/examples/async_pi_estimate/async.h
@@ -1,15 +1,14 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #ifndef EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_
 #define EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_
 
-#include <node.h>
 #include <nan.h>
 
 NAN_METHOD(CalculateAsync);
diff --git a/examples/async_pi_estimate/pi_est.cc b/examples/async_pi_estimate/pi_est.cc
index 59d0f5e..ea9ed57 100644
--- a/examples/async_pi_estimate/pi_est.cc
+++ b/examples/async_pi_estimate/pi_est.cc
@@ -1,13 +1,13 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <cstdlib>
-#include "./pi_est.h"
+#include "pi_est.h"  // NOLINT(build/include)
 
 /*
 Estimate the value of π by using a Monte Carlo method.
@@ -42,7 +42,7 @@ double Estimate (int points) {
 
   // unique seed for each run, for threaded use
   unsigned int seed = randall(&randseed);
-  
+
 #ifdef _WIN32
   srand(seed);
 #endif
diff --git a/examples/async_pi_estimate/pi_est.h b/examples/async_pi_estimate/pi_est.h
index 7c0bdd3..bba3743 100644
--- a/examples/async_pi_estimate/pi_est.h
+++ b/examples/async_pi_estimate/pi_est.h
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #ifndef EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_
 #define EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_
diff --git a/examples/async_pi_estimate/sync.cc b/examples/async_pi_estimate/sync.cc
index 80edffc..a4d36cb 100644
--- a/examples/async_pi_estimate/sync.cc
+++ b/examples/async_pi_estimate/sync.cc
@@ -1,15 +1,14 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
-#include <node.h>
 #include <nan.h>
-#include "./pi_est.h"
-#include "./sync.h"
+#include "pi_est.h"  // NOLINT(build/include)
+#include "sync.h"  // NOLINT(build/include)
 
 using v8::Number;
 
diff --git a/examples/async_pi_estimate/sync.h b/examples/async_pi_estimate/sync.h
index 37c33e9..e9a0172 100644
--- a/examples/async_pi_estimate/sync.h
+++ b/examples/async_pi_estimate/sync.h
@@ -1,15 +1,14 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #ifndef EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_
 #define EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_
 
-#include <node.h>
 #include <nan.h>
 
 NAN_METHOD(CalculateSync);
diff --git a/nan.h b/nan.h
index 063de4e..fb025a9 100644
--- a/nan.h
+++ b/nan.h
@@ -1,17 +1,18 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors:
+ * Copyright (c) 2015 NAN contributors:
  *   - Rod Vagg <https://github.com/rvagg>
  *   - Benjamin Byholm <https://github.com/kkoopa>
  *   - Trevor Norris <https://github.com/trevnorris>
  *   - Nathan Rajlich <https://github.com/TooTallNate>
  *   - Brett Lawson <https://github.com/brett19>
  *   - Ben Noordhuis <https://github.com/bnoordhuis>
+ *   - David Siegel <https://github.com/agnat>
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
  *
- * Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30
+ * Version 1.8.4: current Node 12: 0.12.2, Node 10: 0.10.38, io.js: 1.8.1
  *
  * See https://github.com/rvagg/nan for the latest update to this file
  **********************************************************************************/
@@ -24,26 +25,171 @@
 #include <node_buffer.h>
 #include <node_version.h>
 #include <node_object_wrap.h>
-#include <string.h>
-#include <limits.h>
-#include <string>
+#include <cstring>
+#include <climits>
+#include <cstdlib>
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4530 )
+# include <string>
+# pragma warning( pop )
+#else
+# include <string>
+#endif
 
-#if defined(__GNUC__) && !defined(DEBUG)
+#if defined(__GNUC__) && !(defined(DEBUG) && DEBUG)
 # define NAN_INLINE inline __attribute__((always_inline))
-#elif defined(_MSC_VER) && !defined(DEBUG)
+#elif defined(_MSC_VER) && !(defined(DEBUG) && DEBUG)
 # define NAN_INLINE __forceinline
 #else
 # define NAN_INLINE inline
 #endif
 
-#if defined(__GNUC__) && !V8_DISABLE_DEPRECATIONS
+#if defined(__GNUC__) && \
+    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
 # define NAN_DEPRECATED __attribute__((deprecated))
-#elif defined(_MSC_VER) && !V8_DISABLE_DEPRECATIONS
+#elif defined(_MSC_VER) && \
+    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
 # define NAN_DEPRECATED __declspec(deprecated)
 #else
 # define NAN_DEPRECATED
 #endif
 
+#define NODE_0_10_MODULE_VERSION 11
+#define NODE_0_12_MODULE_VERSION 12
+#define ATOM_0_21_MODULE_VERSION 41
+#define IOJS_1_0_MODULE_VERSION  42
+#define IOJS_1_1_MODULE_VERSION  43
+
+#if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION)
+typedef v8::InvocationCallback NanFunctionCallback;
+typedef v8::Script             NanUnboundScript;
+typedef v8::Script             NanBoundScript;
+#else
+typedef v8::FunctionCallback   NanFunctionCallback;
+typedef v8::UnboundScript      NanUnboundScript;
+typedef v8::Script             NanBoundScript;
+#endif
+
+#if (NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION)
+typedef v8::String::ExternalAsciiStringResource
+    NanExternalOneByteStringResource;
+#else
+typedef v8::String::ExternalOneByteStringResource
+    NanExternalOneByteStringResource;
+#endif
+
+#include "nan_new.h"  // NOLINT(build/include)
+
+// uv helpers
+#ifdef UV_VERSION_MAJOR
+#ifndef UV_VERSION_PATCH
+#define UV_VERSION_PATCH 0
+#endif
+#define NAUV_UVVERSION  ((UV_VERSION_MAJOR << 16) | \
+                     (UV_VERSION_MINOR <<  8) | \
+                     (UV_VERSION_PATCH))
+#else
+#define NAUV_UVVERSION 0x000b00
+#endif
+
+
+#if NAUV_UVVERSION < 0x000b17
+#define NAUV_WORK_CB(func) \
+    void func(uv_async_t *async, int)
+#else
+#define NAUV_WORK_CB(func) \
+    void func(uv_async_t *async)
+#endif
+
+#if NAUV_UVVERSION >= 0x000b0b
+
+typedef uv_key_t nauv_key_t;
+
+inline int nauv_key_create(nauv_key_t *key) {
+  return uv_key_create(key);
+}
+
+inline void nauv_key_delete(nauv_key_t *key) {
+  uv_key_delete(key);
+}
+
+inline void* nauv_key_get(nauv_key_t *key) {
+  return uv_key_get(key);
+}
+
+inline void nauv_key_set(nauv_key_t *key, void *value) {
+  uv_key_set(key, value);
+}
+
+#else
+
+/* Implement thread local storage for older versions of libuv.
+ * This is essentially a backport of libuv commit 5d2434bf
+ * written by Ben Noordhuis, adjusted for names and inline.
+ */
+
+#ifndef WIN32
+
+#include <pthread.h>
+
+typedef pthread_key_t nauv_key_t;
+
+inline int nauv_key_create(nauv_key_t* key) {
+  return -pthread_key_create(key, NULL);
+}
+
+inline void nauv_key_delete(nauv_key_t* key) {
+  if (pthread_key_delete(*key))
+    abort();
+}
+
+inline void* nauv_key_get(nauv_key_t* key) {
+  return pthread_getspecific(*key);
+}
+
+inline void nauv_key_set(nauv_key_t* key, void* value) {
+  if (pthread_setspecific(*key, value))
+    abort();
+}
+
+#else
+
+#include <windows.h>
+
+typedef struct {
+  DWORD tls_index;
+} nauv_key_t;
+
+inline int nauv_key_create(nauv_key_t* key) {
+  key->tls_index = TlsAlloc();
+  if (key->tls_index == TLS_OUT_OF_INDEXES)
+    return UV_ENOMEM;
+  return 0;
+}
+
+inline void nauv_key_delete(nauv_key_t* key) {
+  if (TlsFree(key->tls_index) == FALSE)
+    abort();
+  key->tls_index = TLS_OUT_OF_INDEXES;
+}
+
+inline void* nauv_key_get(nauv_key_t* key) {
+  void* value = TlsGetValue(key->tls_index);
+  if (value == NULL)
+    if (GetLastError() != ERROR_SUCCESS)
+      abort();
+  return value;
+}
+
+inline void nauv_key_set(nauv_key_t* key, void* value) {
+  if (TlsSetValue(key->tls_index, value) == FALSE)
+    abort();
+}
+
+#endif
+#endif
+
 // some generic helpers
 
 template<typename T> NAN_INLINE bool NanSetPointerSafe(
@@ -103,8 +249,84 @@ NAN_INLINE uint32_t NanUInt32OptionValue(
       : def;
 }
 
-#if (NODE_MODULE_VERSION > 0x000B)
-// Node 0.11+ (0.11.3 and below won't compile with these)
+template<typename T>
+v8::Local<T> NanNew(v8::Handle<T>);
+
+template<typename T>
+NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Handle<T> val) {
+  return NanNew(val);
+}
+
+template<typename T>
+NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Local<T> val) {
+  return val;
+}
+
+template<typename T>
+NAN_INLINE v8::Local<v8::Value> _NanEnsureLocal(T val) {
+  return NanNew(val);
+}
+
+/* io.js 1.0  */
+#if NODE_MODULE_VERSION >= IOJS_1_0_MODULE_VERSION \
+  || NODE_VERSION_AT_LEAST(0, 11, 15)
+  NAN_INLINE
+  void NanSetCounterFunction(v8::CounterLookupCallback cb) {
+    v8::Isolate::GetCurrent()->SetCounterFunction(cb);
+  }
+
+  NAN_INLINE
+  void NanSetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
+    v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb);
+  }
+
+  NAN_INLINE
+  void NanSetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
+    v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb);
+  }
+
+  NAN_INLINE bool NanIdleNotification(int idle_time_in_ms) {
+    return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms);
+  }
+
+  NAN_INLINE void NanLowMemoryNotification() {
+    v8::Isolate::GetCurrent()->LowMemoryNotification();
+  }
+
+  NAN_INLINE void NanContextDisposedNotification() {
+    v8::Isolate::GetCurrent()->ContextDisposedNotification();
+  }
+#else
+  NAN_INLINE
+  void NanSetCounterFunction(v8::CounterLookupCallback cb) {
+    v8::V8::SetCounterFunction(cb);
+  }
+
+  NAN_INLINE
+  void NanSetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
+    v8::V8::SetCreateHistogramFunction(cb);
+  }
+
+  NAN_INLINE
+  void NanSetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
+    v8::V8::SetAddHistogramSampleFunction(cb);
+  }
+
+  NAN_INLINE bool NanIdleNotification(int idle_time_in_ms) {
+    return v8::V8::IdleNotification(idle_time_in_ms);
+  }
+
+  NAN_INLINE void NanLowMemoryNotification() {
+    v8::V8::LowMemoryNotification();
+  }
+
+  NAN_INLINE void NanContextDisposedNotification() {
+    v8::V8::ContextDisposedNotification();
+  }
+#endif
+
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+// Node 0.11+ (0.11.12 and below won't compile with these)
 
 # define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo<v8::Value>&
 # define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args
@@ -169,342 +391,23 @@ NAN_INLINE uint32_t NanUInt32OptionValue(
 # define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args
 # define _NAN_INDEX_QUERY_RETURN_TYPE void
 
-  typedef v8::FunctionCallback NanFunctionCallback;
-
-  template<typename T>
-  NAN_INLINE v8::Local<T> NanNew() {
-    return T::New(v8::Isolate::GetCurrent());
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<T> NanNew(P arg1) {
-    return T::New(v8::Isolate::GetCurrent(), arg1);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<v8::Signature> NanNew(
-      v8::Handle<v8::FunctionTemplate> receiver
-    , int argc
-    , v8::Handle<v8::FunctionTemplate> argv[] = 0) {
-    return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<v8::FunctionTemplate> NanNew(
-      NanFunctionCallback callback
-    , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
-    , v8::Handle<v8::Signature> signature = v8::Handle<v8::Signature>()) {
-    return T::New(v8::Isolate::GetCurrent(), callback, data, signature);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<T> NanNew(v8::Handle<T> arg1) {
-    return v8::Local<T>::New(v8::Isolate::GetCurrent(), arg1);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<T> NanNew(const v8::Persistent<T> &arg1) {
-    return v8::Local<T>::New(v8::Isolate::GetCurrent(), arg1);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<T> NanNew(P arg1, int arg2) {
-    return T::New(v8::Isolate::GetCurrent(), arg1, arg2);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Array> NanNew<v8::Array>() {
-    return v8::Array::New(v8::Isolate::GetCurrent());
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Array> NanNew<v8::Array>(int length) {
-    return v8::Array::New(v8::Isolate::GetCurrent(), length);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Date> NanNew<v8::Date>(double time) {
-    return v8::Date::New(v8::Isolate::GetCurrent(), time).As<v8::Date>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Date> NanNew<v8::Date>(int time) {
-    return v8::Date::New(v8::Isolate::GetCurrent(), time).As<v8::Date>();
-  }
-
-  typedef v8::UnboundScript NanUnboundScript;
-  typedef v8::Script NanBoundScript;
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<T> NanNew(
-      P s
-    , const v8::ScriptOrigin& origin
-  ) {
-    v8::ScriptCompiler::Source source(s, origin);
-    return v8::ScriptCompiler::CompileUnbound(
-        v8::Isolate::GetCurrent(), &source);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<NanUnboundScript> NanNew<NanUnboundScript>(
-      v8::Local<v8::String> s
-  ) {
-    v8::ScriptCompiler::Source source(s);
-    return v8::ScriptCompiler::CompileUnbound(
-        v8::Isolate::GetCurrent(), &source);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::BooleanObject> NanNew(bool value) {
-    return v8::BooleanObject::New(value).As<v8::BooleanObject>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::StringObject>
-  NanNew<v8::StringObject, v8::Local<v8::String> >(
-      v8::Local<v8::String> value) {
-    return v8::StringObject::New(value).As<v8::StringObject>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::StringObject>
-  NanNew<v8::StringObject, v8::Handle<v8::String> >(
-      v8::Handle<v8::String> value) {
-    return v8::StringObject::New(value).As<v8::StringObject>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::NumberObject> NanNew<v8::NumberObject>(double val) {
-    return v8::NumberObject::New(
-        v8::Isolate::GetCurrent(), val).As<v8::NumberObject>();
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<v8::RegExp> NanNew(
-      v8::Handle<v8::String> pattern, v8::RegExp::Flags flags) {
-    return v8::RegExp::New(pattern, flags);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<v8::RegExp> NanNew(
-      v8::Local<v8::String> pattern, v8::RegExp::Flags flags) {
-    return v8::RegExp::New(pattern, flags);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<v8::RegExp> NanNew(
-      v8::Handle<v8::String> pattern, v8::RegExp::Flags flags) {
-    return v8::RegExp::New(pattern, flags);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<v8::RegExp> NanNew(
-      v8::Local<v8::String> pattern, v8::RegExp::Flags flags) {
-    return v8::RegExp::New(pattern, flags);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Uint32> NanNew<v8::Uint32, int32_t>(int32_t val) {
-    return v8::Uint32::NewFromUnsigned(
-        v8::Isolate::GetCurrent(), val)->ToUint32();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Uint32> NanNew<v8::Uint32, uint32_t>(uint32_t val) {
-    return v8::Uint32::NewFromUnsigned(
-        v8::Isolate::GetCurrent(), val)->ToUint32();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Int32> NanNew<v8::Int32, int32_t>(int32_t val) {
-    return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Int32> NanNew<v8::Int32, uint32_t>(uint32_t val) {
-    return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, char *>(
-      char *arg
-    , int length) {
-    return v8::String::NewFromUtf8(
-        v8::Isolate::GetCurrent()
-      , arg
-      , v8::String::kNormalString
-      , length);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, const char *>(
-      const char *arg
-    , int length) {
-    return v8::String::NewFromUtf8(
-        v8::Isolate::GetCurrent()
-      , arg
-      , v8::String::kNormalString
-      , length);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, char *>(char *arg) {
-    return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, const char *>(
-      const char *arg) {
-    return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, uint8_t *>(
-      uint8_t *arg
-    , int length) {
-    return v8::String::NewFromOneByte(
-        v8::Isolate::GetCurrent()
-      , arg
-      , v8::String::kNormalString
-      , length);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, const uint8_t *>(
-      const uint8_t *arg
-    , int length) {
-    return v8::String::NewFromOneByte(
-        v8::Isolate::GetCurrent()
-      , arg
-      , v8::String::kNormalString
-      , length);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, uint8_t *>(uint8_t *arg) {
-    return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, const uint8_t *>(
-      const uint8_t *arg) {
-    return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, uint16_t *>(
-      uint16_t *arg
-    , int length) {
-    return v8::String::NewFromTwoByte(
-        v8::Isolate::GetCurrent()
-      , arg
-      , v8::String::kNormalString
-      , length);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, const uint16_t *>(
-      const uint16_t *arg
-    , int length) {
-    return v8::String::NewFromTwoByte(
-        v8::Isolate::GetCurrent()
-      , arg
-      , v8::String::kNormalString
-      , length);
-  }
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, uint16_t *>(
-      uint16_t *arg) {
-    return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, const uint16_t *>(
-      const uint16_t *arg) {
-    return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, std::string>(
-      std::string arg) {
-    return NanNew<v8::String>(arg.c_str(), arg.size());
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String>() {
-    return v8::String::Empty(v8::Isolate::GetCurrent());
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(const char* arg, int length = -1) {
-    return NanNew<v8::String>(arg, length);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      const uint8_t* arg
-    , int length = -1) {
-    return NanNew<v8::String>(arg, length);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      const uint16_t* arg
-    , int length = -1) {
-    return NanNew<v8::String>(arg, length);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      const std::string& arg) {
-    return NanNew<v8::String>(arg.c_str(), arg.size());
-  }
-
-  NAN_INLINE v8::Local<v8::Number> NanNew(double val) {
-    return NanNew<v8::Number>(val);
-  }
-
-  NAN_INLINE v8::Local<v8::Integer> NanNew(int val) {
-    return NanNew<v8::Integer>(val);
-  }
-
-  NAN_INLINE v8::Local<v8::Uint32> NanNew(unsigned int val) {
-    return NanNew<v8::Uint32>(val);
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanNew(bool val) {
-    return NanNew<v8::Boolean>(val);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      v8::String::ExternalStringResource *resource) {
-    return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      v8::String::ExternalAsciiStringResource *resource) {
-    return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource);
-  }
-
 # define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent())
 # define NanEscapableScope()                                                   \
   v8::EscapableHandleScope scope(v8::Isolate::GetCurrent())
 
-  template<typename T>
-  NAN_INLINE v8::Local<T> _NanEscapeScopeHelper(v8::Handle<T> val) {
-    return NanNew(val);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<T> _NanEscapeScopeHelper(v8::Local<T> val) {
-    return val;
-  }
-
-# define NanEscapeScope(val) scope.Escape(_NanEscapeScopeHelper(val))
+# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
 # define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent())
 # define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent())
-# define NanReturnValue(value) return args.GetReturnValue().Set(value)
+# define NanReturnValue(value) return args.GetReturnValue().Set(_NanEnsureLocal(value))
 # define NanReturnUndefined() return
+# define NanReturnHolder() NanReturnValue(args.Holder())
+# define NanReturnThis() NanReturnValue(args.This())
 # define NanReturnNull() return args.GetReturnValue().SetNull()
 # define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString()
 
-# define NanObjectWrapHandle(obj) obj->handle()
+  NAN_INLINE v8::Local<v8::Object> NanObjectWrapHandle(const node::ObjectWrap *obj) {
+    return const_cast<node::ObjectWrap*>(obj)->handle();
+  }
 
   NAN_INLINE v8::Local<v8::Primitive> NanUndefined() {
     NanEscapableScope();
@@ -563,6 +466,9 @@ NAN_INLINE uint32_t NanUInt32OptionValue(
     object->SetAlignedPointerInInternalField(index, value);
   }
 
+# define NAN_GC_CALLBACK(name)                                                 \
+    void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags)
+
   NAN_INLINE void NanAddGCEpilogueCallback(
       v8::Isolate::GCEpilogueCallback callback
     , v8::GCType gc_type_filter = v8::kGCTypeAll) {
@@ -778,13 +684,13 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
   }
 
   NAN_INLINE bool NanHasInstance(
-      v8::Persistent<v8::FunctionTemplate>& function_template
+      const v8::Persistent<v8::FunctionTemplate>& function_template
     , v8::Handle<v8::Value> value
   ) {
     return NanNew(function_template)->HasInstance(value);
   }
 
-  NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
+  NAN_DEPRECATED NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
       v8::ExtensionConfiguration* extensions = NULL
     , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
     , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
@@ -869,23 +775,32 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
    public:
     NAN_INLINE explicit NanAsciiString(v8::Handle<v8::Value> from) {
       v8::Local<v8::String> toStr = from->ToString();
-      int buf_size = toStr->Length() + 1;
-      buf = new char[buf_size];
-      size = toStr->WriteOneByte(
-          reinterpret_cast<unsigned char*>(buf), 0, buf_size);
+      size = toStr->Length();
+      buf = new char[size + 1];
+      size = toStr->WriteOneByte(reinterpret_cast<unsigned char*>(buf));
     }
 
-    NAN_INLINE int Size() const {
+    NAN_DEPRECATED NAN_INLINE int Size() const {
       return size;
     }
 
+    NAN_INLINE int length() const {
+      return size;
+    }
+
+
     NAN_INLINE char* operator*() { return buf; }
+    NAN_INLINE const char* operator*() const { return buf; }
 
     NAN_INLINE ~NanAsciiString() {
       delete[] buf;
     }
 
    private:
+    // disallow copying and assigning
+    NanAsciiString(const NanAsciiString&);
+    void operator=(const NanAsciiString&);
+
     char *buf;
     int size;
   };
@@ -894,22 +809,31 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
    public:
     NAN_INLINE explicit NanUtf8String(v8::Handle<v8::Value> from) {
       v8::Local<v8::String> toStr = from->ToString();
-      int buf_size = toStr->Utf8Length() + 1;
-      buf = new char[buf_size];
-      size = toStr->WriteUtf8(buf, buf_size);
+      size = toStr->Utf8Length();
+      buf = new char[size + 1];
+      toStr->WriteUtf8(buf);
     }
 
-    NAN_INLINE int Size() const {
+    NAN_DEPRECATED NAN_INLINE int Size() const {
+      return size;
+    }
+
+    NAN_INLINE int length() const {
       return size;
     }
 
     NAN_INLINE char* operator*() { return buf; }
+    NAN_INLINE const char* operator*() const { return buf; }
 
     NAN_INLINE ~NanUtf8String() {
       delete[] buf;
     }
 
    private:
+    // disallow copying and assigning
+    NanUtf8String(const NanUtf8String&);
+    void operator=(const NanUtf8String&);
+
     char *buf;
     int size;
   };
@@ -918,22 +842,31 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
    public:
     NAN_INLINE explicit NanUcs2String(v8::Handle<v8::Value> from) {
       v8::Local<v8::String> toStr = from->ToString();
-      int buf_size = toStr->Length() + 1;
-      buf = new uint16_t[buf_size];
-      size = toStr->Write(buf, 0, buf_size);
+      size = toStr->Length();
+      buf = new uint16_t[size + 1];
+      toStr->Write(buf);
     }
 
-    NAN_INLINE int Size() const {
+    NAN_DEPRECATED NAN_INLINE int Size() const {
+      return size;
+    }
+
+    NAN_INLINE int length() const {
       return size;
     }
 
     NAN_INLINE uint16_t* operator*() { return buf; }
+    NAN_INLINE const uint16_t* operator*() const { return buf; }
 
     NAN_INLINE ~NanUcs2String() {
       delete[] buf;
     }
 
    private:
+    // disallow copying and assigning
+    NanUcs2String(const NanUcs2String&);
+    void operator=(const NanUcs2String&);
+
     uint16_t *buf;
     int size;
   };
@@ -993,296 +926,26 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
 # define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args
 # define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle<v8::Integer>
 
-  typedef v8::InvocationCallback NanFunctionCallback;
-
   NAN_DEPRECATED NAN_INLINE v8::Local<v8::String> NanSymbol(
       const char* data, int length = -1) {
     return v8::String::NewSymbol(data, length);
   }
 
-  template<typename T>
-  NAN_INLINE v8::Local<T> NanNew() {
-    return v8::Local<T>::New(T::New());
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<T> NanNew(v8::Handle<T> arg) {
-    return v8::Local<T>::New(arg);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<v8::Signature> NanNew(
-      v8::Handle<v8::FunctionTemplate> receiver
-    , int argc
-    , v8::Handle<v8::FunctionTemplate> argv[] = 0) {
-    return v8::Signature::New(receiver, argc, argv);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<v8::FunctionTemplate> NanNew(
-      NanFunctionCallback callback
-    , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
-    , v8::Handle<v8::Signature> signature = v8::Handle<v8::Signature>()) {
-    return T::New(callback, data, signature);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<T> NanNew(const v8::Persistent<T> &arg) {
-    return v8::Local<T>::New(arg);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<T> NanNew(P arg) {
-    return v8::Local<T>::New(T::New(arg));
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<T> NanNew(P arg, int length) {
-    return v8::Local<T>::New(T::New(arg, length));
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<v8::RegExp> NanNew(
-      v8::Handle<v8::String> pattern, v8::RegExp::Flags flags) {
-    return v8::RegExp::New(pattern, flags);
-  }
-
-  template<typename T>
-  NAN_INLINE v8::Local<v8::RegExp> NanNew(
-      v8::Local<v8::String> pattern, v8::RegExp::Flags flags) {
-    return v8::RegExp::New(pattern, flags);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<v8::RegExp> NanNew(
-      v8::Handle<v8::String> pattern, v8::RegExp::Flags flags) {
-    return v8::RegExp::New(pattern, flags);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<v8::RegExp> NanNew(
-      v8::Local<v8::String> pattern, v8::RegExp::Flags flags) {
-    return v8::RegExp::New(pattern, flags);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Array> NanNew<v8::Array>() {
-    return v8::Array::New();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Array> NanNew<v8::Array>(int length) {
-    return v8::Array::New(length);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Date> NanNew<v8::Date>(double time) {
-    return v8::Date::New(time).As<v8::Date>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Date> NanNew<v8::Date>(int time) {
-    return v8::Date::New(time).As<v8::Date>();
-  }
-
-  typedef v8::Script NanUnboundScript;
-  typedef v8::Script NanBoundScript;
-
-  template<typename T, typename P>
-  NAN_INLINE v8::Local<T> NanNew(
-      P s
-    , const v8::ScriptOrigin& origin
-  ) {
-    return v8::Script::New(s, const_cast<v8::ScriptOrigin *>(&origin));
-  }
-
-  template<>
-  NAN_INLINE v8::Local<NanUnboundScript> NanNew<NanUnboundScript>(
-      v8::Local<v8::String> s
-  ) {
-    return v8::Script::New(s);
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::BooleanObject> NanNew(bool value) {
-    return v8::BooleanObject::New(value).As<v8::BooleanObject>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::StringObject>
-  NanNew<v8::StringObject, v8::Local<v8::String> >(
-      v8::Local<v8::String> value) {
-    return v8::StringObject::New(value).As<v8::StringObject>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::StringObject>
-  NanNew<v8::StringObject, v8::Handle<v8::String> >(
-      v8::Handle<v8::String> value) {
-    return v8::StringObject::New(value).As<v8::StringObject>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::NumberObject> NanNew<v8::NumberObject>(double val) {
-    return v8::NumberObject::New(val).As<v8::NumberObject>();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Uint32> NanNew<v8::Uint32, int32_t>(int32_t val) {
-    return v8::Uint32::NewFromUnsigned(val)->ToUint32();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Uint32> NanNew<v8::Uint32, uint32_t>(uint32_t val) {
-    return v8::Uint32::NewFromUnsigned(val)->ToUint32();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Int32> NanNew<v8::Int32, int32_t>(int32_t val) {
-    return v8::Int32::New(val)->ToInt32();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::Int32> NanNew<v8::Int32, uint32_t>(uint32_t val) {
-    return v8::Int32::New(val)->ToInt32();
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, uint8_t *>(
-      uint8_t *arg
-    , int length) {
-    int len = length;
-    if (len < 0) {
-      size_t temp = strlen(reinterpret_cast<const char *>(arg));
-      assert(temp <= INT_MAX && "too long string");
-      len = static_cast<int>(temp);
-    }
-    uint16_t *warg = new uint16_t[len];
-    for (int i = 0; i < len; i++) {
-      warg[i] = arg[i];
-    }
-    v8::Local<v8::String> retval = v8::String::New(warg, len);
-    delete[] warg;
-    return retval;
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, const uint8_t *>(
-      const uint8_t *arg
-    , int length) {
-    int len = length;
-    if (len < 0) {
-      size_t temp = strlen(reinterpret_cast<const char *>(arg));
-      assert(temp <= INT_MAX && "too long string");
-      len = static_cast<int>(temp);
-    }
-    uint16_t *warg = new uint16_t[len];
-    for (int i = 0; i < len; i++) {
-      warg[i] = arg[i];
-    }
-    v8::Local<v8::String> retval = v8::String::New(warg, len);
-    delete[] warg;
-    return retval;
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, uint8_t *>(uint8_t *arg) {
-    size_t temp = strlen(reinterpret_cast<char *>(arg));
-    assert(temp <= INT_MAX && "too long string");
-    int length = static_cast<int>(temp);
-    uint16_t *warg = new uint16_t[length];
-    for (int i = 0; i < length; i++) {
-      warg[i] = arg[i];
-    }
-
-    v8::Local<v8::String> retval = v8::String::New(warg, length);
-    delete[] warg;
-    return retval;
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, const uint8_t *>(
-      const uint8_t *arg) {
-    size_t temp = strlen(reinterpret_cast<const char *>(arg));
-    assert(temp <= INT_MAX && "too long string");
-    int length = static_cast<int>(temp);
-    uint16_t *warg = new uint16_t[length];
-    for (int i = 0; i < length; i++) {
-      warg[i] = arg[i];
-    }
-    v8::Local<v8::String> retval = v8::String::New(warg, length);
-    delete[] warg;
-    return retval;
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String, std::string>(
-      std::string arg) {
-    return NanNew<v8::String>(arg.c_str(), arg.size());
-  }
-
-  template<>
-  NAN_INLINE v8::Local<v8::String> NanNew<v8::String>() {
-    return v8::String::Empty();
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(const char* arg, int length = -1) {
-    return NanNew<v8::String>(arg, length);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      const uint8_t* arg
-    , int length = -1) {
-    return NanNew<v8::String>(arg, length);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      const uint16_t* arg
-    , int length = -1) {
-    return NanNew<v8::String>(arg, length);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      std::string& arg) {
-    return NanNew<v8::String>(arg.c_str(), arg.size());
-  }
-
-  NAN_INLINE v8::Local<v8::Number> NanNew(double val) {
-    return NanNew<v8::Number>(val);
-  }
-
-  NAN_INLINE v8::Local<v8::Integer> NanNew(int val) {
-    return NanNew<v8::Integer>(val);
-  }
-
-  NAN_INLINE v8::Local<v8::Uint32> NanNew(unsigned int val) {
-    return NanNew<v8::Uint32>(val);
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanNew(bool val) {
-    return NanNew<v8::Boolean>(val);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      v8::String::ExternalStringResource *resource) {
-    return v8::String::NewExternal(resource);
-  }
-
-  NAN_INLINE v8::Local<v8::String> NanNew(
-      v8::String::ExternalAsciiStringResource *resource) {
-    return v8::String::NewExternal(resource);
-  }
-
 # define NanScope() v8::HandleScope scope
 # define NanEscapableScope() v8::HandleScope scope
 # define NanEscapeScope(val) scope.Close(val)
 # define NanLocker() v8::Locker locker
 # define NanUnlocker() v8::Unlocker unlocker
-# define NanReturnValue(value) return scope.Close(value)
+# define NanReturnValue(value) return scope.Close(_NanEnsureLocal(value))
+# define NanReturnHolder() NanReturnValue(args.Holder())
+# define NanReturnThis() NanReturnValue(args.This())
 # define NanReturnUndefined() return v8::Undefined()
 # define NanReturnNull() return v8::Null()
 # define NanReturnEmptyString() return v8::String::Empty()
-# define NanObjectWrapHandle(obj) v8::Local<v8::Object>::New(obj->handle_)
+
+  NAN_INLINE v8::Local<v8::Object> NanObjectWrapHandle(const node::ObjectWrap *obj) {
+    return v8::Local<v8::Object>::New(obj->handle_);
+  }
 
   NAN_INLINE v8::Local<v8::Primitive> NanUndefined() {
     NanEscapableScope();
@@ -1340,6 +1003,9 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
     object->SetPointerInInternalField(index, value);
   }
 
+# define NAN_GC_CALLBACK(name)                                                 \
+    void name(v8::GCType type, v8::GCCallbackFlags flags)
+
   NAN_INLINE void NanAddGCEpilogueCallback(
     v8::GCEpilogueCallback callback
   , v8::GCType gc_type_filter = v8::kGCTypeAll) {
@@ -1542,7 +1208,7 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
       const char *data
     , uint32_t size
   ) {
-#if NODE_MODULE_VERSION >= 0x000B
+#if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION
     return NanNew(node::Buffer::New(data, size)->handle_);
 #else
     return NanNew(
@@ -1567,13 +1233,13 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
   }
 
   NAN_INLINE bool NanHasInstance(
-      v8::Persistent<v8::FunctionTemplate>& function_template
+      const v8::Persistent<v8::FunctionTemplate>& function_template
     , v8::Handle<v8::Value> value
   ) {
     return function_template->HasInstance(value);
   }
 
-  NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
+  NAN_DEPRECATED NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
       v8::ExtensionConfiguration* extensions = NULL
     , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
     , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
@@ -1610,7 +1276,7 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
     return NanNew(node::MakeCallback(target, func, argc, argv));
 # else
     v8::TryCatch try_catch;
-    v8::Local<v8::Value> result = NanNew(func->Call(target, argc, argv));
+    v8::Local<v8::Value> result = func->Call(target, argc, argv);
     if (try_catch.HasCaught()) {
         node::FatalException(try_catch);
     }
@@ -1662,22 +1328,32 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
    public:
     NAN_INLINE explicit NanAsciiString(v8::Handle<v8::Value> from) {
       v8::Local<v8::String> toStr = from->ToString();
-      int buf_size = toStr->Length() + 1;
-      buf = new char[buf_size];
-      size = toStr->WriteAscii(buf, 0, buf_size);
+      size = toStr->Length();
+      buf = new char[size + 1];
+      size = toStr->WriteAscii(buf);
+    }
+
+    NAN_DEPRECATED NAN_INLINE int Size() const {
+      return size;
     }
 
-    NAN_INLINE int Size() const {
+    NAN_INLINE int length() const {
       return size;
     }
 
+
     NAN_INLINE char* operator*() { return buf; }
+    NAN_INLINE const char* operator*() const { return buf; }
 
     NAN_INLINE ~NanAsciiString() {
       delete[] buf;
     }
 
    private:
+    // disallow copying and assigning
+    NanAsciiString(const NanAsciiString&);
+    void operator=(const NanAsciiString&);
+
     char *buf;
     int size;
   };
@@ -1686,22 +1362,31 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
    public:
     NAN_INLINE explicit NanUtf8String(v8::Handle<v8::Value> from) {
       v8::Local<v8::String> toStr = from->ToString();
-      int buf_size = toStr->Utf8Length() + 1;
-      buf = new char[buf_size];
-      size = toStr->WriteUtf8(buf, buf_size);
+      size = toStr->Utf8Length();
+      buf = new char[size + 1];
+      toStr->WriteUtf8(buf);
+    }
+
+    NAN_DEPRECATED NAN_INLINE int Size() const {
+      return size;
     }
 
-    NAN_INLINE int Size() const {
+    NAN_INLINE int length() const {
       return size;
     }
 
     NAN_INLINE char* operator*() { return buf; }
+    NAN_INLINE const char* operator*() const { return buf; }
 
     NAN_INLINE ~NanUtf8String() {
       delete[] buf;
     }
 
    private:
+    // disallow copying and assigning
+    NanUtf8String(const NanUtf8String&);
+    void operator=(const NanUtf8String&);
+
     char *buf;
     int size;
   };
@@ -1710,22 +1395,31 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
    public:
     NAN_INLINE explicit NanUcs2String(v8::Handle<v8::Value> from) {
       v8::Local<v8::String> toStr = from->ToString();
-      int buf_size = toStr->Length() + 1;
-      buf = new uint16_t[buf_size];
-      size = toStr->Write(buf, 0, buf_size);
+      size = toStr->Length();
+      buf = new uint16_t[size + 1];
+      toStr->Write(buf);
     }
 
-    NAN_INLINE int Size() const {
+    NAN_DEPRECATED NAN_INLINE int Size() const {
+      return size;
+    }
+
+    NAN_INLINE int length() const {
       return size;
     }
 
     NAN_INLINE uint16_t* operator*() { return buf; }
+    NAN_INLINE const uint16_t* operator*() const { return buf; }
 
     NAN_INLINE ~NanUcs2String() {
       delete[] buf;
     }
 
    private:
+    // disallow copying and assigning
+    NanUcs2String(const NanUcs2String&);
+    void operator=(const NanUcs2String&);
+
     uint16_t *buf;
     int size;
   };
@@ -1799,6 +1493,17 @@ class NanCallback {
     NanDisposePersistent(handle);
   }
 
+  bool operator==(const NanCallback &other) const {
+    NanScope();
+    v8::Local<v8::Value> a = NanNew(handle)->Get(kCallbackIndex);
+    v8::Local<v8::Value> b = NanNew(other.handle)->Get(kCallbackIndex);
+    return a->StrictEquals(b);
+  }
+
+  bool operator!=(const NanCallback &other) const {
+    return !this->operator==(other);
+  }
+
   NAN_INLINE void SetFunction(const v8::Handle<v8::Function> &fn) {
     NanScope();
     NanNew(handle)->Set(kCallbackIndex, fn);
@@ -1815,15 +1520,49 @@ class NanCallback {
     return NanNew(handle)->Get(kCallbackIndex)->IsUndefined();
   }
 
-  v8::Handle<v8::Value> Call(int argc, v8::Handle<v8::Value> argv[]) const {
+  NAN_INLINE v8::Handle<v8::Value>
+  Call(v8::Handle<v8::Object> target
+     , int argc
+     , v8::Handle<v8::Value> argv[]) const {
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    return Call_(isolate, target, argc, argv);
+#else
+    return Call_(target, argc, argv);
+#endif
+  }
+
+  NAN_INLINE v8::Handle<v8::Value>
+  Call(int argc, v8::Handle<v8::Value> argv[]) const {
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    return Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv);
+#else
+    return Call_(v8::Context::GetCurrent()->Global(), argc, argv);
+#endif
+  }
+
+ private:
+  v8::Persistent<v8::Object> handle;
+  static const uint32_t kCallbackIndex = 0;
+
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+  v8::Handle<v8::Value> Call_(v8::Isolate *isolate
+                           , v8::Handle<v8::Object> target
+                           , int argc
+                           , v8::Handle<v8::Value> argv[]) const {
+#else
+  v8::Handle<v8::Value> Call_(v8::Handle<v8::Object> target
+                           , int argc
+                           , v8::Handle<v8::Value> argv[]) const {
+#endif
     NanEscapableScope();
-#if (NODE_MODULE_VERSION > 0x000B)  // 0.11.12+
-    v8::Isolate* isolate = v8::Isolate::GetCurrent();
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
     v8::Local<v8::Function> callback = NanNew(handle)->
         Get(kCallbackIndex).As<v8::Function>();
     return NanEscapeScope(node::MakeCallback(
         isolate
-      , isolate->GetCurrentContext()->Global()
+      , target
       , callback
       , argc
       , argv
@@ -1833,7 +1572,7 @@ class NanCallback {
     v8::Local<v8::Function> callback = handle->
         Get(kCallbackIndex).As<v8::Function>();
     return NanEscapeScope(node::MakeCallback(
-        v8::Context::GetCurrent()->Global()
+        target
       , callback
       , argc
       , argv
@@ -1842,20 +1581,16 @@ class NanCallback {
     v8::Local<v8::Function> callback = handle->
         Get(kCallbackIndex).As<v8::Function>();
     return NanEscapeScope(NanMakeCallback(
-        v8::Context::GetCurrent()->Global(), callback, argc, argv));
+        target, callback, argc, argv));
 #endif
 #endif
   }
-
- private:
-  v8::Persistent<v8::Object> handle;
-  static const uint32_t kCallbackIndex = 0;
 };
 
 /* abstract */ class NanAsyncWorker {
  public:
-  explicit NanAsyncWorker(NanCallback *callback)
-      : callback(callback), errmsg_(NULL) {
+  explicit NanAsyncWorker(NanCallback *callback_)
+      : callback(callback_), errmsg_(NULL) {
     request.data = this;
 
     NanScope();
@@ -1901,13 +1636,15 @@ class NanCallback {
 
   uv_work_t request;
 
+  virtual void Destroy() {
+      delete this;
+  }
+
  protected:
   v8::Persistent<v8::Object> persistentHandle;
   NanCallback *callback;
 
   virtual void HandleOKCallback() {
-    NanScope();
-
     callback->Call(0, NULL);
   }
 
@@ -1938,6 +1675,112 @@ class NanCallback {
   char *errmsg_;
 };
 
+/* abstract */ class NanAsyncProgressWorker : public NanAsyncWorker {
+ public:
+  explicit NanAsyncProgressWorker(NanCallback *callback_)
+      : NanAsyncWorker(callback_), asyncdata_(NULL), asyncsize_(0) {
+    async = new uv_async_t;
+    uv_async_init(
+        uv_default_loop()
+      , async
+      , AsyncProgress_
+    );
+    async->data = this;
+
+    uv_mutex_init(&async_lock);
+  }
+
+  virtual ~NanAsyncProgressWorker() {
+    uv_mutex_destroy(&async_lock);
+
+    if (asyncdata_) {
+      delete[] asyncdata_;
+    }
+  }
+
+  void WorkProgress() {
+    uv_mutex_lock(&async_lock);
+    char *data = asyncdata_;
+    size_t size = asyncsize_;
+    asyncdata_ = NULL;
+    uv_mutex_unlock(&async_lock);
+
+    // Dont send progress events after we've already completed.
+    if (callback) {
+        HandleProgressCallback(data, size);
+    }
+    delete[] data;
+  }
+
+  class ExecutionProgress {
+    friend class NanAsyncProgressWorker;
+   public:
+    // You could do fancy generics with templates here.
+    void Send(const char* data, size_t size) const {
+        that_->SendProgress_(data, size);
+    }
+
+   private:
+    explicit ExecutionProgress(NanAsyncProgressWorker* that) : that_(that) {}
+    // Prohibit copying and assignment.
+    ExecutionProgress(const ExecutionProgress&);
+    void operator=(const ExecutionProgress&);
+  #if __cplusplus >= 201103L
+    // Prohibit C++11 move semantics.
+    ExecutionProgress(ExecutionProgress&&) = delete;
+    void operator=(ExecutionProgress&&) = delete;
+  #endif
+    NanAsyncProgressWorker* const that_;
+  };
+
+  virtual void Execute(const ExecutionProgress& progress) = 0;
+  virtual void HandleProgressCallback(const char *data, size_t size) = 0;
+
+  virtual void Destroy() {
+      uv_close(reinterpret_cast<uv_handle_t*>(async), AsyncClose_);
+  }
+
+ private:
+  void Execute() /*final override*/ {
+      ExecutionProgress progress(this);
+      Execute(progress);
+  }
+
+  void SendProgress_(const char *data, size_t size) {
+    char *new_data = new char[size];
+    memcpy(new_data, data, size);
+
+    uv_mutex_lock(&async_lock);
+    char *old_data = asyncdata_;
+    asyncdata_ = new_data;
+    asyncsize_ = size;
+    uv_mutex_unlock(&async_lock);
+
+    if (old_data) {
+      delete[] old_data;
+    }
+    uv_async_send(async);
+  }
+
+  NAN_INLINE static NAUV_WORK_CB(AsyncProgress_) {
+    NanAsyncProgressWorker *worker =
+            static_cast<NanAsyncProgressWorker*>(async->data);
+    worker->WorkProgress();
+  }
+
+  NAN_INLINE static void AsyncClose_(uv_handle_t* handle) {
+    NanAsyncProgressWorker *worker =
+            static_cast<NanAsyncProgressWorker*>(handle->data);
+    delete reinterpret_cast<uv_async_t*>(handle);
+    delete worker;
+  }
+
+  uv_async_t *async;
+  uv_mutex_t async_lock;
+  char *asyncdata_;
+  size_t asyncsize_;
+};
+
 NAN_INLINE void NanAsyncExecute (uv_work_t* req) {
   NanAsyncWorker *worker = static_cast<NanAsyncWorker*>(req->data);
   worker->Execute();
@@ -1946,7 +1789,7 @@ NAN_INLINE void NanAsyncExecute (uv_work_t* req) {
 NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) {
   NanAsyncWorker* worker = static_cast<NanAsyncWorker*>(req->data);
   worker->WorkComplete();
-  delete worker;
+  worker->Destroy();
 }
 
 NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) {
@@ -2086,6 +1929,30 @@ template<typename T> static size_t _nan_hex_decode(
   return i;
 }
 
+namespace NanIntern {
+
+inline
+NanExternalOneByteStringResource const*
+GetExternalResource(v8::Local<v8::String> str) {
+#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
+    return str->GetExternalAsciiStringResource();
+#else
+    return str->GetExternalOneByteStringResource();
+#endif
+}
+
+inline
+bool
+IsExternal(v8::Local<v8::String> str) {
+#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
+    return str->IsExternalAscii();
+#else
+    return str->IsExternalOneByte();
+#endif
+}
+
+}  // end of namespace NanIntern
+
 static bool _NanGetExternalParts(
     v8::Handle<v8::Value> val
   , const char** data
@@ -2100,14 +1967,15 @@ static bool _NanGetExternalParts(
   assert(val->IsString());
   v8::Local<v8::String> str = NanNew(val.As<v8::String>());
 
-  if (str->IsExternalAscii()) {
-    const v8::String::ExternalAsciiStringResource* ext;
-    ext = str->GetExternalAsciiStringResource();
+  if (NanIntern::IsExternal(str)) {
+    const NanExternalOneByteStringResource* ext;
+    ext = NanIntern::GetExternalResource(str);
     *data = ext->data();
     *len = ext->length();
     return true;
+  }
 
-  } else if (str->IsExternal()) {
+  if (str->IsExternal()) {
     const v8::String::ExternalStringResource* ext;
     ext = str->GetExternalStringResource();
     *data = reinterpret_cast<const char*>(ext->data());
@@ -2122,6 +1990,85 @@ namespace Nan {
   enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
 }
 
+#if !NODE_VERSION_AT_LEAST(0, 10, 0)
+# include "nan_string_bytes.h"  // NOLINT(build/include)
+#endif
+
+NAN_INLINE v8::Local<v8::Value> NanEncode(
+    const void *buf, size_t len, enum Nan::Encoding encoding = Nan::BINARY) {
+#if (NODE_MODULE_VERSION >= ATOM_0_21_MODULE_VERSION)
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  node::encoding node_enc = static_cast<node::encoding>(encoding);
+
+  if (encoding == Nan::UCS2) {
+    return node::Encode(
+        isolate
+      , reinterpret_cast<const uint16_t *>(buf)
+      , len / 2);
+  } else {
+    return node::Encode(
+        isolate
+      , reinterpret_cast<const char *>(buf)
+      , len
+      , node_enc);
+  }
+#elif (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+  return node::Encode(
+      v8::Isolate::GetCurrent()
+    , buf, len
+    , static_cast<node::encoding>(encoding));
+#else
+# if NODE_VERSION_AT_LEAST(0, 10, 0)
+  return node::Encode(buf, len, static_cast<node::encoding>(encoding));
+# else
+  return NanIntern::Encode(reinterpret_cast<const char*>(buf), len, encoding);
+# endif
+#endif
+}
+
+NAN_INLINE ssize_t NanDecodeBytes(
+    v8::Handle<v8::Value> val, enum Nan::Encoding encoding = Nan::BINARY) {
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+  return node::DecodeBytes(
+      v8::Isolate::GetCurrent()
+    , val
+    , static_cast<node::encoding>(encoding));
+#else
+# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
+  if (encoding == Nan::BUFFER) {
+    return node::DecodeBytes(val, node::BINARY);
+  }
+# endif
+  return node::DecodeBytes(val, static_cast<node::encoding>(encoding));
+#endif
+}
+
+NAN_INLINE ssize_t NanDecodeWrite(
+    char *buf
+  , size_t len
+  , v8::Handle<v8::Value> val
+  , enum Nan::Encoding encoding = Nan::BINARY) {
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+  return node::DecodeWrite(
+      v8::Isolate::GetCurrent()
+    , buf
+    , len
+    , val
+    , static_cast<node::encoding>(encoding));
+#else
+# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
+  if (encoding == Nan::BUFFER) {
+    return node::DecodeWrite(buf, len, val, node::BINARY);
+  }
+# endif
+  return node::DecodeWrite(
+      buf
+    , len
+    , val
+    , static_cast<node::encoding>(encoding));
+#endif
+}
+
 /* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString(
     v8::Handle<v8::Value> from
   , enum Nan::Encoding encoding
@@ -2152,7 +2099,7 @@ namespace Nan {
 
   switch (encoding) {
     case Nan::ASCII:
-#if NODE_MODULE_VERSION < 0x000C
+#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
       sz_ = toStr->Length();
       if (to == NULL) {
         to = new char[sz_ + term_len];
@@ -2172,19 +2119,19 @@ namespace Nan {
       } else {
         assert(buflen >= sz_ + term_len && "too small buffer");
       }
-#if NODE_MODULE_VERSION < 0x000C
+#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
       {
         uint16_t* twobytebuf = new uint16_t[sz_ + term_len];
 
-        size_t len = toStr->Write(twobytebuf, 0,
+        size_t somelen = toStr->Write(twobytebuf, 0,
           static_cast<int>(sz_ + term_len), flags);
 
-        for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) {
+        for (size_t i = 0; i < sz_ + term_len && i < somelen + term_len; i++) {
           unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
           to[i] = *b;
         }
 
-        NanSetPointerSafe<size_t>(datalen, len);
+        NanSetPointerSafe<size_t>(datalen, somelen);
 
         delete[] twobytebuf;
         return to;
@@ -2328,4 +2275,48 @@ NAN_INLINE void NanSetInstanceTemplate(
   NanSetTemplate(templ->InstanceTemplate(), name, value, attributes);
 }
 
+//=== Export ==================================================================
+
+inline
+void
+NanExport(v8::Handle<v8::Object> target, const char * name,
+    NanFunctionCallback f) {
+  target->Set(NanNew<v8::String>(name),
+      NanNew<v8::FunctionTemplate>(f)->GetFunction());
+}
+
+//=== Tap Reverse Binding =====================================================
+
+struct NanTap {
+  explicit NanTap(v8::Handle<v8::Value> t) : t_() {
+    NanAssignPersistent(t_, t->ToObject());
+  }
+
+  ~NanTap() { NanDisposePersistent(t_); }  // not sure if neccessary
+
+  inline void plan(int i) {
+    v8::Handle<v8::Value> arg = NanNew(i);
+    NanMakeCallback(NanNew(t_), "plan", 1, &arg);
+  }
+
+  inline void ok(bool isOk, const char * msg = NULL) {
+    v8::Handle<v8::Value> args[2];
+    args[0] = NanNew(isOk);
+    if (msg) args[1] = NanNew(msg);
+    NanMakeCallback(NanNew(t_), "ok", msg ? 2 : 1, args);
+  }
+
+ private:
+  v8::Persistent<v8::Object> t_;
+};
+
+#define NAN_STRINGIZE2(x) #x
+#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x)
+#define NAN_TEST_EXPRESSION(expression) \
+  ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression
+
+#define return_NanValue(v) NanReturnValue(v)
+#define return_NanUndefined() NanReturnUndefined()
+#define NAN_EXPORT(target, function) NanExport(target, #function, function)
+
 #endif  // NAN_H_
diff --git a/nan_implementation_12_inl.h b/nan_implementation_12_inl.h
new file mode 100644
index 0000000..fc0e0ac
--- /dev/null
+++ b/nan_implementation_12_inl.h
@@ -0,0 +1,261 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_IMPLEMENTATION_12_INL_H_
+#define NAN_IMPLEMENTATION_12_INL_H_
+//==============================================================================
+// node v0.11 implementation
+//==============================================================================
+
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4530 )
+# include <string>
+# pragma warning( pop )
+#else
+# include <string>
+#endif
+
+namespace NanIntern {
+
+//=== Array ====================================================================
+
+Factory<v8::Array>::return_t
+Factory<v8::Array>::New() {
+  return v8::Array::New(v8::Isolate::GetCurrent());
+}
+
+Factory<v8::Array>::return_t
+Factory<v8::Array>::New(int length) {
+  return v8::Array::New(v8::Isolate::GetCurrent(), length);
+}
+
+//=== Boolean ==================================================================
+
+Factory<v8::Boolean>::return_t
+Factory<v8::Boolean>::New(bool value) {
+  return v8::Boolean::New(v8::Isolate::GetCurrent(), value);
+}
+
+//=== Boolean Object ===========================================================
+
+Factory<v8::BooleanObject>::return_t
+Factory<v8::BooleanObject>::New(bool value) {
+  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
+}
+
+//=== Context ==================================================================
+
+Factory<v8::Context>::return_t
+Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
+                         , v8::Handle<v8::ObjectTemplate> tmpl
+                         , v8::Handle<v8::Value> obj) {
+  return v8::Context::New(v8::Isolate::GetCurrent(), extensions, tmpl, obj);
+}
+
+//=== Date =====================================================================
+
+Factory<v8::Date>::return_t
+Factory<v8::Date>::New(double value) {
+  return v8::Date::New(v8::Isolate::GetCurrent(), value).As<v8::Date>();
+}
+
+//=== External =================================================================
+
+Factory<v8::External>::return_t
+Factory<v8::External>::New(void * value) {
+  return v8::External::New(v8::Isolate::GetCurrent(), value);
+}
+
+//=== Function =================================================================
+
+Factory<v8::Function>::return_t
+Factory<v8::Function>::New( NanFunctionCallback callback
+                          , v8::Handle<v8::Value> data) {
+  return v8::Function::New( v8::Isolate::GetCurrent()
+                          , callback
+                          , data);
+}
+
+//=== Function Template ========================================================
+
+Factory<v8::FunctionTemplate>::return_t
+Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
+                                  , v8::Handle<v8::Value> data
+                                  , v8::Handle<v8::Signature> signature) {
+  return v8::FunctionTemplate::New( v8::Isolate::GetCurrent()
+                                  , callback
+                                  , data
+                                  , signature);
+}
+
+//=== Number ===================================================================
+
+Factory<v8::Number>::return_t
+Factory<v8::Number>::New(double value) {
+  return v8::Number::New(v8::Isolate::GetCurrent(), value);
+}
+
+//=== Number Object ============================================================
+
+Factory<v8::NumberObject>::return_t
+Factory<v8::NumberObject>::New(double value) {
+  return v8::NumberObject::New( v8::Isolate::GetCurrent()
+                              , value).As<v8::NumberObject>();
+}
+
+//=== Integer, Int32 and Uint32 ================================================
+
+template <typename T>
+typename IntegerFactory<T>::return_t
+IntegerFactory<T>::New(int32_t value) {
+  return To<T>(T::New(v8::Isolate::GetCurrent(), value));
+}
+
+template <typename T>
+typename IntegerFactory<T>::return_t
+IntegerFactory<T>::New(uint32_t value) {
+  return To<T>(T::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
+}
+
+Factory<v8::Uint32>::return_t
+Factory<v8::Uint32>::New(int32_t value) {
+  return To<v8::Uint32>(
+      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
+}
+
+Factory<v8::Uint32>::return_t
+Factory<v8::Uint32>::New(uint32_t value) {
+  return To<v8::Uint32>(
+      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
+}
+
+//=== Object ===================================================================
+
+Factory<v8::Object>::return_t
+Factory<v8::Object>::New() {
+  return v8::Object::New(v8::Isolate::GetCurrent());
+}
+
+//=== Object Template ==========================================================
+
+Factory<v8::ObjectTemplate>::return_t
+Factory<v8::ObjectTemplate>::New() {
+  return v8::ObjectTemplate::New(v8::Isolate::GetCurrent());
+}
+
+//=== RegExp ===================================================================
+
+Factory<v8::RegExp>::return_t
+Factory<v8::RegExp>::New(
+    v8::Handle<v8::String> pattern
+  , v8::RegExp::Flags flags) {
+  return v8::RegExp::New(pattern, flags);
+}
+
+//=== Script ===================================================================
+
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source) {
+  v8::ScriptCompiler::Source src(source);
+  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
+}
+
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source
+                        , v8::ScriptOrigin const& origin) {
+  v8::ScriptCompiler::Source src(source, origin);
+  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
+}
+
+//=== Signature ================================================================
+
+Factory<v8::Signature>::return_t
+Factory<v8::Signature>::New(Factory<v8::Signature>::FTH receiver) {
+  return v8::Signature::New(v8::Isolate::GetCurrent(), receiver);
+}
+
+//=== String ===================================================================
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New() {
+  return v8::String::Empty(v8::Isolate::GetCurrent());
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const char * value, int length) {
+  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value,
+      v8::String::kNormalString, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(std::string const& value) {
+  assert(value.size() <= INT_MAX && "string too long");
+  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(),
+      value.data(), v8::String::kNormalString, static_cast<int>(value.size()));
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const uint8_t * value, int length) {
+  return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
+        v8::String::kNormalString, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const uint16_t * value, int length) {
+  return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value,
+        v8::String::kNormalString, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
+  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(NanExternalOneByteStringResource * value) {
+  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
+}
+
+//=== String Object ============================================================
+
+Factory<v8::StringObject>::return_t
+Factory<v8::StringObject>::New(v8::Handle<v8::String> value) {
+  return v8::StringObject::New(value).As<v8::StringObject>();
+}
+
+//=== Unbound Script ===========================================================
+
+Factory<v8::UnboundScript>::return_t
+Factory<v8::UnboundScript>::New(v8::Local<v8::String> source) {
+  v8::ScriptCompiler::Source src(source);
+  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
+}
+
+Factory<v8::UnboundScript>::return_t
+Factory<v8::UnboundScript>::New( v8::Local<v8::String> source
+                               , v8::ScriptOrigin const& origin) {
+  v8::ScriptCompiler::Source src(source, origin);
+  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
+}
+
+}  // end of namespace NanIntern
+
+//=== Presistents and Handles ==================================================
+
+template <typename T>
+inline v8::Local<T> NanNew(v8::Handle<T> h) {
+  return v8::Local<T>::New(v8::Isolate::GetCurrent(), h);
+}
+
+template <typename T>
+inline v8::Local<T> NanNew(v8::Persistent<T> const& p) {
+  return v8::Local<T>::New(v8::Isolate::GetCurrent(), p);
+}
+
+#endif  // NAN_IMPLEMENTATION_12_INL_H_
diff --git a/nan_implementation_pre_12_inl.h b/nan_implementation_pre_12_inl.h
new file mode 100644
index 0000000..e995a14
--- /dev/null
+++ b/nan_implementation_pre_12_inl.h
@@ -0,0 +1,267 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_IMPLEMENTATION_PRE_12_INL_H_
+#define NAN_IMPLEMENTATION_PRE_12_INL_H_
+
+#include <algorithm>
+
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4530 )
+# include <string>
+# include <vector>
+# pragma warning( pop )
+#else
+# include <string>
+# include <vector>
+#endif
+
+//==============================================================================
+// node v0.10 implementation
+//==============================================================================
+
+namespace NanIntern {
+
+//=== Array ====================================================================
+
+Factory<v8::Array>::return_t
+Factory<v8::Array>::New() {
+  return v8::Array::New();
+}
+
+Factory<v8::Array>::return_t
+Factory<v8::Array>::New(int length) {
+  return v8::Array::New(length);
+}
+
+//=== Boolean ==================================================================
+
+Factory<v8::Boolean>::return_t
+Factory<v8::Boolean>::New(bool value) {
+  return v8::Boolean::New(value)->ToBoolean();
+}
+
+//=== Boolean Object ===========================================================
+
+Factory<v8::BooleanObject>::return_t
+Factory<v8::BooleanObject>::New(bool value) {
+  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
+}
+
+//=== Context ==================================================================
+
+Factory<v8::Context>::return_t
+Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
+                         , v8::Handle<v8::ObjectTemplate> tmpl
+                         , v8::Handle<v8::Value> obj) {
+  v8::Persistent<v8::Context> ctx = v8::Context::New(extensions, tmpl, obj);
+  v8::Local<v8::Context> lctx = v8::Local<v8::Context>::New(ctx);
+  ctx.Dispose();
+  return lctx;
+}
+
+//=== Date =====================================================================
+
+Factory<v8::Date>::return_t
+Factory<v8::Date>::New(double value) {
+  return v8::Date::New(value).As<v8::Date>();
+}
+
+//=== External =================================================================
+
+Factory<v8::External>::return_t
+Factory<v8::External>::New(void * value) {
+  return v8::External::New(value);
+}
+
+//=== Function =================================================================
+
+Factory<v8::Function>::return_t
+Factory<v8::Function>::New( NanFunctionCallback callback
+                          , v8::Handle<v8::Value> data) {
+  return Factory<v8::FunctionTemplate>::New( callback
+                                           , data
+                                           , v8::Handle<v8::Signature>()
+                                           )->GetFunction();
+}
+
+
+//=== FunctionTemplate =========================================================
+
+Factory<v8::FunctionTemplate>::return_t
+Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
+                                  , v8::Handle<v8::Value> data
+                                  , v8::Handle<v8::Signature> signature) {
+  // Note(agnat): Emulate length argument here. Unfortunately, I couldn't find
+  // a way. Have at it though...
+  return v8::FunctionTemplate::New( callback
+                                  , data
+                                  , signature);
+}
+
+//=== Number ===================================================================
+
+Factory<v8::Number>::return_t
+Factory<v8::Number>::New(double value) {
+  return v8::Number::New(value);
+}
+
+//=== Number Object ============================================================
+
+Factory<v8::NumberObject>::return_t
+Factory<v8::NumberObject>::New(double value) {
+  return v8::NumberObject::New(value).As<v8::NumberObject>();
+}
+
+//=== Integer, Int32 and Uint32 ================================================
+
+template <typename T>
+typename IntegerFactory<T>::return_t
+IntegerFactory<T>::New(int32_t value) {
+  return To<T>(T::New(value));
+}
+
+template <typename T>
+typename IntegerFactory<T>::return_t
+IntegerFactory<T>::New(uint32_t value) {
+  return To<T>(T::NewFromUnsigned(value));
+}
+
+Factory<v8::Uint32>::return_t
+Factory<v8::Uint32>::New(int32_t value) {
+  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
+}
+
+Factory<v8::Uint32>::return_t
+Factory<v8::Uint32>::New(uint32_t value) {
+  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
+}
+
+
+//=== Object ===================================================================
+
+Factory<v8::Object>::return_t
+Factory<v8::Object>::New() {
+  return v8::Object::New();
+}
+
+//=== Object Template ==========================================================
+
+Factory<v8::ObjectTemplate>::return_t
+Factory<v8::ObjectTemplate>::New() {
+  return v8::ObjectTemplate::New();
+}
+
+//=== RegExp ===================================================================
+
+Factory<v8::RegExp>::return_t
+Factory<v8::RegExp>::New(
+    v8::Handle<v8::String> pattern
+  , v8::RegExp::Flags flags) {
+  return v8::RegExp::New(pattern, flags);
+}
+
+//=== Script ===================================================================
+
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source) {
+  return v8::Script::New(source);
+}
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source
+                        , v8::ScriptOrigin const& origin) {
+  return v8::Script::New(source, const_cast<v8::ScriptOrigin*>(&origin));
+}
+
+//=== Signature ================================================================
+
+Factory<v8::Signature>::return_t
+Factory<v8::Signature>::New(Factory<v8::Signature>::FTH receiver) {
+  return v8::Signature::New(receiver);
+}
+
+//=== String ===================================================================
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New() {
+  return v8::String::Empty();
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const char * value, int length) {
+  return v8::String::New(value, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(std::string const& value) {
+  assert(value.size() <= INT_MAX && "string too long");
+  return v8::String::New( value.data(), static_cast<int>(value.size()));
+}
+
+inline
+void
+widenString(std::vector<uint16_t> *ws, const uint8_t *s, int l = -1) {
+  size_t len = static_cast<size_t>(l);
+  if (l < 0) {
+    len = strlen(reinterpret_cast<const char*>(s));
+  }
+  assert(len <= INT_MAX && "string too long");
+  ws->resize(len);
+  std::copy(s, s + len, ws->begin());
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const uint16_t * value, int length) {
+  return v8::String::New(value, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const uint8_t * value, int length) {
+  std::vector<uint16_t> wideString;
+  widenString(&wideString, value, length);
+  if (wideString.size() == 0) {
+    return v8::String::Empty();
+  } else {
+    return v8::String::New(&wideString.front()
+         , static_cast<int>(wideString.size()));
+  }
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
+  return v8::String::NewExternal(value);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(v8::String::ExternalAsciiStringResource * value) {
+  return v8::String::NewExternal(value);
+}
+
+//=== String Object ============================================================
+
+Factory<v8::StringObject>::return_t
+Factory<v8::StringObject>::New(v8::Handle<v8::String> value) {
+  return v8::StringObject::New(value).As<v8::StringObject>();
+}
+
+}  // end of namespace NanIntern
+
+//=== Presistents and Handles ==================================================
+
+template <typename T>
+inline v8::Local<T> NanNew(v8::Handle<T> h) {
+  return v8::Local<T>::New(h);
+}
+
+template <typename T>
+inline v8::Local<T> NanNew(v8::Persistent<T> const& p) {
+  return v8::Local<T>::New(p);
+}
+
+#endif  // NAN_IMPLEMENTATION_PRE_12_INL_H_
diff --git a/nan_new.h b/nan_new.h
new file mode 100644
index 0000000..c189092
--- /dev/null
+++ b/nan_new.h
@@ -0,0 +1,328 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_NEW_H_
+#define NAN_NEW_H_
+
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4530 )
+# include <string>
+# pragma warning( pop )
+#else
+# include <string>
+#endif
+
+namespace NanIntern {  // scnr
+
+// TODO(agnat): Generalize
+template <typename T> v8::Local<T> To(v8::Handle<v8::Integer> i);
+
+template <>
+inline
+v8::Local<v8::Integer>
+To<v8::Integer>(v8::Handle<v8::Integer> i) { return i->ToInteger(); }
+
+template <>
+inline
+v8::Local<v8::Int32>
+To<v8::Int32>(v8::Handle<v8::Integer> i)   { return i->ToInt32(); }
+
+template <>
+inline
+v8::Local<v8::Uint32>
+To<v8::Uint32>(v8::Handle<v8::Integer> i)  { return i->ToUint32(); }
+
+template <typename T> struct FactoryBase { typedef v8::Local<T> return_t; };
+
+template <typename T> struct Factory;
+
+template <>
+struct Factory<v8::Array> : FactoryBase<v8::Array> {
+  static inline return_t New();
+  static inline return_t New(int length);
+};
+
+template <>
+struct Factory<v8::Boolean> : FactoryBase<v8::Boolean> {
+  static inline return_t New(bool value);
+};
+
+template <>
+struct Factory<v8::BooleanObject> : FactoryBase<v8::BooleanObject> {
+  static inline return_t New(bool value);
+};
+
+template <>
+struct Factory<v8::Context> : FactoryBase<v8::Context> {
+  static inline
+  return_t
+  New( v8::ExtensionConfiguration* extensions = NULL
+     , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
+     , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>());
+};
+
+template <>
+struct Factory<v8::Date> : FactoryBase<v8::Date> {
+  static inline return_t New(double value);
+};
+
+template <>
+struct Factory<v8::External> : FactoryBase<v8::External> {
+  static inline return_t New(void *value);
+};
+
+template <>
+struct Factory<v8::Function> : FactoryBase<v8::Function> {
+  static inline
+  return_t
+  New( NanFunctionCallback callback
+     , v8::Handle<v8::Value> data = v8::Handle<v8::Value>());
+};
+
+template <>
+struct Factory<v8::FunctionTemplate> : FactoryBase<v8::FunctionTemplate> {
+  static inline
+  return_t
+  New( NanFunctionCallback callback = NULL
+     , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
+     , v8::Handle<v8::Signature> signature = v8::Handle<v8::Signature>());
+};
+
+template <>
+struct Factory<v8::Number> : FactoryBase<v8::Number> {
+  static inline return_t New(double value);
+};
+
+template <>
+struct Factory<v8::NumberObject> : FactoryBase<v8::NumberObject> {
+  static inline return_t New(double value);
+};
+
+template <typename T>
+struct IntegerFactory : FactoryBase<T> {
+  typedef typename FactoryBase<T>::return_t return_t;
+  static inline return_t New(int32_t value);
+  static inline return_t New(uint32_t value);
+};
+
+template <>
+struct Factory<v8::Integer> : IntegerFactory<v8::Integer> {};
+
+template <>
+struct Factory<v8::Int32> : IntegerFactory<v8::Int32> {};
+
+template <>
+struct Factory<v8::Uint32> : FactoryBase<v8::Uint32> {
+  static inline return_t New(int32_t value);
+  static inline return_t New(uint32_t value);
+};
+
+template <>
+struct Factory<v8::Object> : FactoryBase<v8::Object> {
+  static inline return_t New();
+};
+
+template <>
+struct Factory<v8::ObjectTemplate> : FactoryBase<v8::ObjectTemplate> {
+  static inline return_t New();
+};
+
+template <>
+struct Factory<v8::RegExp> : FactoryBase<v8::RegExp> {
+  static inline return_t New(
+      v8::Handle<v8::String> pattern, v8::RegExp::Flags flags);
+};
+
+template <>
+struct Factory<v8::Script> : FactoryBase<v8::Script> {
+  static inline return_t New( v8::Local<v8::String> source);
+  static inline return_t New( v8::Local<v8::String> source
+                            , v8::ScriptOrigin const& origin);
+};
+
+template <>
+struct Factory<v8::Signature> : FactoryBase<v8::Signature> {
+  typedef v8::Handle<v8::FunctionTemplate> FTH;
+  static inline return_t New(FTH receiver = FTH());
+};
+
+template <>
+struct Factory<v8::String> : FactoryBase<v8::String> {
+  static inline return_t New();
+  static inline return_t New(const char *value, int length = -1);
+  static inline return_t New(const uint16_t *value, int length = -1);
+  static inline return_t New(std::string const& value);
+
+  static inline return_t New(v8::String::ExternalStringResource * value);
+  static inline return_t New(NanExternalOneByteStringResource * value);
+
+  // TODO(agnat): Deprecate.
+  static inline return_t New(const uint8_t * value, int length = -1);
+};
+
+template <>
+struct Factory<v8::StringObject> : FactoryBase<v8::StringObject> {
+  static inline return_t New(v8::Handle<v8::String> value);
+};
+
+}  // end of namespace NanIntern
+
+#if (NODE_MODULE_VERSION >= 12)
+
+namespace NanIntern {
+
+template <>
+struct Factory<v8::UnboundScript> : FactoryBase<v8::UnboundScript> {
+  static inline return_t New( v8::Local<v8::String> source);
+  static inline return_t New( v8::Local<v8::String> source
+                            , v8::ScriptOrigin const& origin);
+};
+
+}  // end of namespace NanIntern
+
+# include "nan_implementation_12_inl.h"
+
+#else  // NODE_MODULE_VERSION >= 12
+
+# include "nan_implementation_pre_12_inl.h"
+
+#endif
+
+//=== API ======================================================================
+
+template <typename T>
+typename NanIntern::Factory<T>::return_t
+NanNew() {
+  return NanIntern::Factory<T>::New();
+}
+
+template <typename T, typename A0>
+typename NanIntern::Factory<T>::return_t
+NanNew(A0 arg0) {
+  return NanIntern::Factory<T>::New(arg0);
+}
+
+template <typename T, typename A0, typename A1>
+typename NanIntern::Factory<T>::return_t
+NanNew(A0 arg0, A1 arg1) {
+  return NanIntern::Factory<T>::New(arg0, arg1);
+}
+
+template <typename T, typename A0, typename A1, typename A2>
+typename NanIntern::Factory<T>::return_t
+NanNew(A0 arg0, A1 arg1, A2 arg2) {
+  return NanIntern::Factory<T>::New(arg0, arg1, arg2);
+}
+
+template <typename T, typename A0, typename A1, typename A2, typename A3>
+typename NanIntern::Factory<T>::return_t
+NanNew(A0 arg0, A1 arg1, A2 arg2, A3 arg3) {
+  return NanIntern::Factory<T>::New(arg0, arg1, arg2, arg3);
+}
+
+// Note(agnat): When passing overloaded function pointers to template functions
+// as generic arguments the compiler needs help in picking the right overload.
+// These two functions handle NanNew<Function> and NanNew<FunctionTemplate> with
+// all argument variations.
+
+// v8::Function and v8::FunctionTemplate with one or two arguments
+template <typename T>
+typename NanIntern::Factory<T>::return_t
+NanNew( NanFunctionCallback callback
+      , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()) {
+    return NanIntern::Factory<T>::New(callback, data);
+}
+
+// v8::Function and v8::FunctionTemplate with three arguments
+template <typename T, typename A2>
+typename NanIntern::Factory<T>::return_t
+NanNew( NanFunctionCallback callback
+      , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
+      , A2 a2 = A2()) {
+    return NanIntern::Factory<T>::New(callback, data, a2);
+}
+
+// Convenience
+
+template <typename T> inline v8::Local<T> NanNew(v8::Handle<T> h);
+template <typename T> inline v8::Local<T> NanNew(v8::Persistent<T> const& p);
+
+inline
+NanIntern::Factory<v8::Boolean>::return_t
+NanNew(bool value) {
+  return NanNew<v8::Boolean>(value);
+}
+
+inline
+NanIntern::Factory<v8::Int32>::return_t
+NanNew(int32_t value) {
+  return NanNew<v8::Int32>(value);
+}
+
+inline
+NanIntern::Factory<v8::Uint32>::return_t
+NanNew(uint32_t value) {
+  return NanNew<v8::Uint32>(value);
+}
+
+inline
+NanIntern::Factory<v8::Number>::return_t
+NanNew(double value) {
+  return NanNew<v8::Number>(value);
+}
+
+inline
+NanIntern::Factory<v8::String>::return_t
+NanNew(std::string const& value) {
+  return NanNew<v8::String>(value);
+}
+
+inline
+NanIntern::Factory<v8::String>::return_t
+NanNew(const char * value, int length) {
+  return NanNew<v8::String>(value, length);
+}
+
+inline
+NanIntern::Factory<v8::String>::return_t
+NanNew(const char * value) {
+  return NanNew<v8::String>(value);
+}
+
+inline
+NanIntern::Factory<v8::String>::return_t
+NanNew(const uint8_t * value) {
+  return NanNew<v8::String>(value);
+}
+
+inline
+NanIntern::Factory<v8::String>::return_t
+NanNew(const uint16_t * value) {
+  return NanNew<v8::String>(value);
+}
+
+inline
+NanIntern::Factory<v8::String>::return_t
+NanNew(v8::String::ExternalStringResource * value) {
+  return NanNew<v8::String>(value);
+}
+
+inline
+NanIntern::Factory<v8::String>::return_t
+NanNew(NanExternalOneByteStringResource * value) {
+  return NanNew<v8::String>(value);
+}
+
+inline
+NanIntern::Factory<v8::RegExp>::return_t
+NanNew(v8::Handle<v8::String> pattern, v8::RegExp::Flags flags) {
+  return NanNew<v8::RegExp>(pattern, flags);
+}
+
+#endif  // NAN_NEW_H_
diff --git a/nan_string_bytes.h b/nan_string_bytes.h
new file mode 100644
index 0000000..9deecfb
--- /dev/null
+++ b/nan_string_bytes.h
@@ -0,0 +1,312 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef NAN_STRING_BYTES_H_
+#define NAN_STRING_BYTES_H_
+
+// Decodes a v8::Handle<v8::String> or Buffer to a raw char*
+
+#include <node.h>
+#include <node_buffer.h>
+#include <assert.h>
+#include <string.h>  // memcpy
+#include <limits.h>
+
+namespace NanIntern {
+
+using v8::Local;
+using v8::Handle;
+using v8::Object;
+using v8::String;
+using v8::Value;
+
+
+//// Base 64 ////
+
+#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
+
+
+
+//// Nan::HEX ////
+
+static bool contains_non_ascii_slow(const char* buf, size_t len) {
+  for (size_t i = 0; i < len; ++i) {
+    if (buf[i] & 0x80) return true;
+  }
+  return false;
+}
+
+
+static bool contains_non_ascii(const char* src, size_t len) {
+  if (len < 16) {
+    return contains_non_ascii_slow(src, len);
+  }
+
+  const unsigned bytes_per_word = sizeof(void*);
+  const unsigned align_mask = bytes_per_word - 1;
+  const unsigned unaligned = reinterpret_cast<uintptr_t>(src) & align_mask;
+
+  if (unaligned > 0) {
+    const unsigned n = bytes_per_word - unaligned;
+    if (contains_non_ascii_slow(src, n)) return true;
+    src += n;
+    len -= n;
+  }
+
+
+#if defined(__x86_64__) || defined(_WIN64)
+  const uintptr_t mask = 0x8080808080808080ll;
+#else
+  const uintptr_t mask = 0x80808080l;
+#endif
+
+  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
+
+  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
+    if (srcw[i] & mask) return true;
+  }
+
+  const unsigned remainder = len & align_mask;
+  if (remainder > 0) {
+    const size_t offset = len - remainder;
+    if (contains_non_ascii_slow(src + offset, remainder)) return true;
+  }
+
+  return false;
+}
+
+
+static void force_ascii_slow(const char* src, char* dst, size_t len) {
+  for (size_t i = 0; i < len; ++i) {
+    dst[i] = src[i] & 0x7f;
+  }
+}
+
+
+static void force_ascii(const char* src, char* dst, size_t len) {
+  if (len < 16) {
+    force_ascii_slow(src, dst, len);
+    return;
+  }
+
+  const unsigned bytes_per_word = sizeof(void*);
+  const unsigned align_mask = bytes_per_word - 1;
+  const unsigned src_unalign = reinterpret_cast<uintptr_t>(src) & align_mask;
+  const unsigned dst_unalign = reinterpret_cast<uintptr_t>(dst) & align_mask;
+
+  if (src_unalign > 0) {
+    if (src_unalign == dst_unalign) {
+      const unsigned unalign = bytes_per_word - src_unalign;
+      force_ascii_slow(src, dst, unalign);
+      src += unalign;
+      dst += unalign;
+      len -= src_unalign;
+    } else {
+      force_ascii_slow(src, dst, len);
+      return;
+    }
+  }
+
+#if defined(__x86_64__) || defined(_WIN64)
+  const uintptr_t mask = ~0x8080808080808080ll;
+#else
+  const uintptr_t mask = ~0x80808080l;
+#endif
+
+  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
+  uintptr_t* dstw = reinterpret_cast<uintptr_t*>(dst);
+
+  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
+    dstw[i] = srcw[i] & mask;
+  }
+
+  const unsigned remainder = len & align_mask;
+  if (remainder > 0) {
+    const size_t offset = len - remainder;
+    force_ascii_slow(src + offset, dst + offset, remainder);
+  }
+}
+
+
+static size_t base64_encode(const char* src,
+                            size_t slen,
+                            char* dst,
+                            size_t dlen) {
+  // We know how much we'll write, just make sure that there's space.
+  assert(dlen >= base64_encoded_size(slen) &&
+      "not enough space provided for base64 encode");
+
+  dlen = base64_encoded_size(slen);
+
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned i;
+  unsigned k;
+  unsigned n;
+
+  static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                              "abcdefghijklmnopqrstuvwxyz"
+                              "0123456789+/";
+
+  i = 0;
+  k = 0;
+  n = slen / 3 * 3;
+
+  while (i < n) {
+    a = src[i + 0] & 0xff;
+    b = src[i + 1] & 0xff;
+    c = src[i + 2] & 0xff;
+
+    dst[k + 0] = table[a >> 2];
+    dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
+    dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
+    dst[k + 3] = table[c & 0x3f];
+
+    i += 3;
+    k += 4;
+  }
+
+  if (n != slen) {
+    switch (slen - n) {
+      case 1:
+        a = src[i + 0] & 0xff;
+        dst[k + 0] = table[a >> 2];
+        dst[k + 1] = table[(a & 3) << 4];
+        dst[k + 2] = '=';
+        dst[k + 3] = '=';
+        break;
+
+      case 2:
+        a = src[i + 0] & 0xff;
+        b = src[i + 1] & 0xff;
+        dst[k + 0] = table[a >> 2];
+        dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
+        dst[k + 2] = table[(b & 0x0f) << 2];
+        dst[k + 3] = '=';
+        break;
+    }
+  }
+
+  return dlen;
+}
+
+
+static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) {
+  // We know how much we'll write, just make sure that there's space.
+  assert(dlen >= slen * 2 &&
+      "not enough space provided for hex encode");
+
+  dlen = slen * 2;
+  for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) {
+    static const char hex[] = "0123456789abcdef";
+    uint8_t val = static_cast<uint8_t>(src[i]);
+    dst[k + 0] = hex[val >> 4];
+    dst[k + 1] = hex[val & 15];
+  }
+
+  return dlen;
+}
+
+
+
+static Local<Value> Encode(const char* buf,
+                           size_t buflen,
+                           enum Nan::Encoding encoding) {
+  assert(buflen <= node::Buffer::kMaxLength);
+  if (!buflen && encoding != Nan::BUFFER)
+    return NanNew("");
+
+  Local<String> val;
+  switch (encoding) {
+    case Nan::BUFFER:
+      return NanNewBufferHandle(buf, buflen);
+
+    case Nan::ASCII:
+      if (contains_non_ascii(buf, buflen)) {
+        char* out = new char[buflen];
+        force_ascii(buf, out, buflen);
+        val = NanNew<String>(out, buflen);
+        delete[] out;
+      } else {
+        val = NanNew<String>(buf, buflen);
+      }
+      break;
+
+    case Nan::UTF8:
+      val = NanNew<String>(buf, buflen);
+      break;
+
+    case Nan::BINARY: {
+      // TODO(isaacs) use ExternalTwoByteString?
+      const unsigned char *cbuf = reinterpret_cast<const unsigned char*>(buf);
+      uint16_t * twobytebuf = new uint16_t[buflen];
+      for (size_t i = 0; i < buflen; i++) {
+        // XXX is the following line platform independent?
+        twobytebuf[i] = cbuf[i];
+      }
+      val = NanNew<String>(twobytebuf, buflen);
+      delete[] twobytebuf;
+      break;
+    }
+
+    case Nan::BASE64: {
+      size_t dlen = base64_encoded_size(buflen);
+      char* dst = new char[dlen];
+
+      size_t written = base64_encode(buf, buflen, dst, dlen);
+      assert(written == dlen);
+
+      val = NanNew<String>(dst, dlen);
+      delete[] dst;
+      break;
+    }
+
+    case Nan::UCS2: {
+      const uint16_t* data = reinterpret_cast<const uint16_t*>(buf);
+      val = NanNew<String>(data, buflen / 2);
+      break;
+    }
+
+    case Nan::HEX: {
+      size_t dlen = buflen * 2;
+      char* dst = new char[dlen];
+      size_t written = hex_encode(buf, buflen, dst, dlen);
+      assert(written == dlen);
+
+      val = NanNew<String>(dst, dlen);
+      delete[] dst;
+      break;
+    }
+
+    default:
+      assert(0 && "unknown encoding");
+      break;
+  }
+
+  return val;
+}
+
+#undef base64_encoded_size
+
+}  // namespace NanIntern
+
+#endif  // NAN_STRING_BYTES_H_
diff --git a/package.json b/package.json
index a6488db..f5cd328 100644
--- a/package.json
+++ b/package.json
@@ -1,15 +1,15 @@
 {
   "name": "nan",
-  "version": "1.3.0",
+  "version": "1.8.4",
   "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility",
   "main": "include_dirs.js",
   "repository": {
     "type": "git",
-    "url": "git://github.com/rvagg/nan.git"
+    "url": "git://github.com/iojs/nan.git"
   },
   "scripts": {
     "test": "tap --gc test/js/*-test.js",
-    "rebuild-tests": "node-gyp rebuild --directory test"
+    "rebuild-tests": "pangyp rebuild --directory test"
   },
   "contributors": [
     "Rod Vagg <r at va.gg> (https://github.com/rvagg)",
@@ -17,12 +17,14 @@
     "Trevor Norris <trev.norris at gmail.com> (https://github.com/trevnorris)",
     "Nathan Rajlich <nathan at tootallnate.net> (https://github.com/TooTallNate)",
     "Brett Lawson <brett19 at gmail.com> (https://github.com/brett19)",
-    "Ben Noordhuis <info at bnoordhuis.nl> (https://github.com/bnoordhuis)"
+    "Ben Noordhuis <info at bnoordhuis.nl> (https://github.com/bnoordhuis)",
+    "David Siegel <david at artcom.de> (https://github.com/agnat)"
   ],
   "devDependencies": {
     "bindings": "~1.2.1",
-    "node-gyp": "~1.0.1",
-    "tap": "~0.4.12",
+    "node-gyp": "~1.0.2",
+    "pangyp": "~2.0.1",
+    "tap": "~0.7.1",
     "xtend": "~4.0.0"
   },
   "license": "MIT"
diff --git a/test/binding.gyp b/test/binding.gyp
index 062d75d..e7e0a29 100644
--- a/test/binding.gyp
+++ b/test/binding.gyp
@@ -1,134 +1,107 @@
-{"targets": [
+{
+  "target_defaults":
+    {
+        "cflags" : ["-Wall", "-Wextra"],
+        "include_dirs": ["<!(node -e \"require('..')\")"]
+    },
+  "targets": [
     {
         "target_name" : "symbols"
       , "sources"     : [ "cpp/symbols.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "strings"
       , "sources"     : [ "cpp/strings.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "optionvalues"
       , "sources"     : [ "cpp/optionvalues.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "multifile"
       , "sources"     : [ "cpp/multifile1.cpp", "cpp/multifile2.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "news"
       , "sources"     : [ "cpp/news.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "morenews"
       , "sources"     : [ "cpp/morenews.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "returnvalue"
       , "sources"     : [ "cpp/returnvalue.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "returnundefined"
       , "sources"     : [ "cpp/returnundefined.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "returnnull"
       , "sources"     : [ "cpp/returnnull.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "returnemptystring"
       , "sources"     : [ "cpp/returnemptystring.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "asyncworker"
       , "sources"     : [ "cpp/asyncworker.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "settergetter"
       , "sources"     : [ "cpp/settergetter.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "persistent"
       , "sources"     : [ "cpp/persistent.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "weak"
       , "sources"     : [ "cpp/weak.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "bufferworkerpersistent"
       , "sources"     : [ "cpp/bufferworkerpersistent.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
   , {
         "target_name" : "asyncworkererror"
       , "sources"     : [ "cpp/asyncworkererror.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }, {
         "target_name" : "settemplate"
       , "sources"     : [ "cpp/settemplate.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
     , {
         "target_name" : "makecallback"
       , "sources"     : [ "cpp/makecallback.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
     }
     , {
         "target_name" : "isolatedata"
       , "sources"     : [ "cpp/isolatedata.cpp" ]
-      , "include_dirs": [
-            "<!(node -e \"require('..')\")"
-        ]
+    }
+    , {
+        "target_name" : "gc"
+      , "sources"     : [ "cpp/gc.cpp" ]
+    }
+    , {
+        "target_name" : "nannew"
+      , "sources"     : [ "cpp/nannew.cpp" ]
+    }
+    , {
+        "target_name" : "asyncprogressworker"
+      , "sources"     : [ "cpp/asyncprogressworker.cpp" ]
+    }
+    , {
+        "target_name" : "nancallback"
+      , "sources"     : [ "cpp/nancallback.cpp" ]
+    }
+    , {
+        "target_name" : "threadlocal"
+      , "sources"     : [ "cpp/threadlocal.cpp" ]
+    }
+    , {
+        "target_name" : "objectwraphandle"
+      , "sources"     : [ "cpp/objectwraphandle.cpp" ]
     }
 ]}
diff --git a/test/cpp/asyncprogressworker.cpp b/test/cpp/asyncprogressworker.cpp
new file mode 100644
index 0000000..fb41747
--- /dev/null
+++ b/test/cpp/asyncprogressworker.cpp
@@ -0,0 +1,66 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef _WIN32
+#include <unistd.h>
+#define Sleep(x) usleep((x)*1000)
+#endif
+#include <nan.h>
+
+class ProgressWorker : public NanAsyncProgressWorker {
+ public:
+  ProgressWorker(
+      NanCallback *callback
+    , NanCallback *progress
+    , int milliseconds
+    , int iters)
+    : NanAsyncProgressWorker(callback), progress(progress)
+    , milliseconds(milliseconds), iters(iters) {}
+  ~ProgressWorker() {}
+
+  void Execute (const NanAsyncProgressWorker::ExecutionProgress& progress) {
+    for (int i = 0; i < iters; ++i) {
+      progress.Send(reinterpret_cast<const char*>(&i), sizeof(int));
+      Sleep(milliseconds);
+    }
+  }
+
+  void HandleProgressCallback(const char *data, size_t size) {
+    NanScope();
+
+    v8::Local<v8::Value> argv[] = {
+        NanNew<v8::Integer>(*reinterpret_cast<int*>(const_cast<char*>(data)))
+    };
+    progress->Call(1, argv);
+  }
+
+ private:
+  NanCallback *progress;
+  int milliseconds;
+  int iters;
+};
+
+NAN_METHOD(DoProgress) {
+  NanScope();
+  NanCallback *progress = new NanCallback(args[2].As<v8::Function>());
+  NanCallback *callback = new NanCallback(args[3].As<v8::Function>());
+  NanAsyncQueueWorker(new ProgressWorker(
+      callback
+    , progress
+    , args[0]->Uint32Value()
+    , args[1]->Uint32Value()));
+  NanReturnUndefined();
+}
+
+void Init(v8::Handle<v8::Object> exports) {
+  exports->Set(
+      NanNew<v8::String>("a")
+    , NanNew<v8::FunctionTemplate>(DoProgress)->GetFunction());
+}
+
+NODE_MODULE(asyncprogressworker, Init)
diff --git a/test/cpp/asyncworker.cpp b/test/cpp/asyncworker.cpp
index 9ed412a..970d96f 100644
--- a/test/cpp/asyncworker.cpp
+++ b/test/cpp/asyncworker.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #ifndef _WIN32
 #include <unistd.h>
diff --git a/test/cpp/asyncworkererror.cpp b/test/cpp/asyncworkererror.cpp
index 29c61fc..caaf81b 100644
--- a/test/cpp/asyncworkererror.cpp
+++ b/test/cpp/asyncworkererror.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/bufferworkerpersistent.cpp b/test/cpp/bufferworkerpersistent.cpp
index c582ce7..96ff8cf 100644
--- a/test/cpp/bufferworkerpersistent.cpp
+++ b/test/cpp/bufferworkerpersistent.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #ifndef _WIN32
 #include <unistd.h>
diff --git a/test/cpp/gc.cpp b/test/cpp/gc.cpp
new file mode 100644
index 0000000..62f38f7
--- /dev/null
+++ b/test/cpp/gc.cpp
@@ -0,0 +1,38 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#include <nan.h>
+
+static v8::Persistent<v8::Function> callback;
+
+NAN_GC_CALLBACK(gcPrologueCallback) {
+  v8::Local<v8::Value> argv[] = {NanNew<v8::String>("prologue")};
+  NanMakeCallback(NanGetCurrentContext()->Global(), NanNew(callback), 1, argv);
+}
+
+NAN_GC_CALLBACK(gcEpilogueCallback) {
+  v8::Local<v8::Value> argv[] = {NanNew<v8::String>("epilogue")};
+  NanMakeCallback(NanGetCurrentContext()->Global(), NanNew(callback), 1, argv);
+}
+
+NAN_METHOD(Hook) {
+  NanScope();
+  NanAssignPersistent(callback, args[0].As<v8::Function>());
+  NanAddGCPrologueCallback(gcPrologueCallback);
+  NanAddGCEpilogueCallback(gcEpilogueCallback);
+  NanReturnValue(args.Holder());
+}
+
+void Init (v8::Handle<v8::Object> target) {
+  target->Set(
+      NanNew<v8::String>("hook")
+    , NanNew<v8::FunctionTemplate>(Hook)->GetFunction()
+  );
+}
+
+NODE_MODULE(gc, Init)
diff --git a/test/cpp/isolatedata.cpp b/test/cpp/isolatedata.cpp
index 5a6c9c7..6a3071c 100644
--- a/test/cpp/isolatedata.cpp
+++ b/test/cpp/isolatedata.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/makecallback.cpp b/test/cpp/makecallback.cpp
index d65c446..4b67884 100644
--- a/test/cpp/makecallback.cpp
+++ b/test/cpp/makecallback.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
-* NAN - Native Abstractions for Node.js
-*
-* Copyright (c) 2014 NAN contributors
-*
-* MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
-**********************************************************************************/
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/morenews.cpp b/test/cpp/morenews.cpp
index 5748b5a..3595af2 100644
--- a/test/cpp/morenews.cpp
+++ b/test/cpp/morenews.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
@@ -52,7 +52,7 @@ class ExtString : public v8::String::ExternalStringResource {
 };
 
 
-class ExtAsciiString : public v8::String::ExternalAsciiStringResource {
+class ExtAsciiString : public NanExternalOneByteStringResource {
  public:
   ~ExtAsciiString() { }
   const char *data() const { return s; }
diff --git a/test/cpp/multifile1.cpp b/test/cpp/multifile1.cpp
index bac21df..62a0191 100644
--- a/test/cpp/multifile1.cpp
+++ b/test/cpp/multifile1.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 #include "./multifile2.h"
diff --git a/test/cpp/multifile2.cpp b/test/cpp/multifile2.cpp
index 14d644d..b198d42 100644
--- a/test/cpp/multifile2.cpp
+++ b/test/cpp/multifile2.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/multifile2.h b/test/cpp/multifile2.h
index 12868de..80e6dc8 100644
--- a/test/cpp/multifile2.h
+++ b/test/cpp/multifile2.h
@@ -1,15 +1,14 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #ifndef TEST_CPP_MULTIFILE2_H_
 #define TEST_CPP_MULTIFILE2_H_
 
-#include <node.h>
 #include <nan.h>
 
 NAN_METHOD(ReturnString);
diff --git a/test/cpp/nancallback.cpp b/test/cpp/nancallback.cpp
new file mode 100644
index 0000000..0d7877b
--- /dev/null
+++ b/test/cpp/nancallback.cpp
@@ -0,0 +1,52 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#include <nan.h>
+
+
+NAN_METHOD(GlobalContext) {
+  NanScope();
+
+  NanCallback(args[0].As<v8::Function>()).Call(0, NULL);
+  NanReturnUndefined();
+}
+
+NAN_METHOD(SpecificContext) {
+  NanScope();
+
+  NanCallback cb(args[0].As<v8::Function>());
+  cb.Call(NanGetCurrentContext()->Global(), 0, NULL);
+  NanReturnUndefined();
+}
+
+NAN_METHOD(CompareCallbacks) {
+  NanScope();
+
+  NanCallback cb1(args[0].As<v8::Function>());
+  NanCallback cb2(args[1].As<v8::Function>());
+  NanCallback cb3(args[2].As<v8::Function>());
+
+  NanReturnValue(NanNew<v8::Boolean>(cb1 == cb2 && cb1 != cb3));
+}
+
+void Init (v8::Handle<v8::Object> target) {
+  target->Set(
+      NanNew<v8::String>("globalContext")
+    , NanNew<v8::FunctionTemplate>(GlobalContext)->GetFunction()
+  );
+  target->Set(
+      NanNew<v8::String>("specificContext")
+    , NanNew<v8::FunctionTemplate>(SpecificContext)->GetFunction()
+  );
+  target->Set(
+      NanNew<v8::String>("compareCallbacks")
+    , NanNew<v8::FunctionTemplate>(CompareCallbacks)->GetFunction()
+  );
+}
+
+NODE_MODULE(nancallback, Init)
diff --git a/test/cpp/nannew.cpp b/test/cpp/nannew.cpp
new file mode 100644
index 0000000..34cf6f3
--- /dev/null
+++ b/test/cpp/nannew.cpp
@@ -0,0 +1,502 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+// toys used in testing
+// included first, so windows actually defines M_PI
+#ifdef _WIN32
+# define _USE_MATH_DEFINES
+#endif
+#include <nan.h>
+#include <cmath>
+#include <ctime>
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4530 )
+# include <string>
+# pragma warning( pop )
+#else
+# include <string>
+#endif
+
+using namespace v8;  // NOLINT(build/namespaces)
+
+namespace {
+
+template <typename T, typename U>
+struct is_same {
+  static const bool value = false;
+};
+
+template <typename T>
+struct is_same<T, T> {
+  static const bool value = true;
+};
+
+template <typename T, typename U>
+bool
+assertType(U value) {
+  return is_same<v8::Local<T>, U>::value;
+}
+
+bool
+stringMatches(Local<Value> value, const char * match) {
+  String::Utf8Value v(value);
+  return std::string(*v) == std::string(match);
+}
+
+#define _(e) NAN_TEST_EXPRESSION(e)
+
+NAN_METHOD(testArray) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(3);
+
+  t.ok(_( NanNew<Array>()->Length() == 0));
+  t.ok(_( NanNew<Array>(7)->Length() == 7));
+  t.ok(_( assertType<Array>(NanNew<Array>(7))));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testBoolean) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(6);
+
+  t.ok(_( NanNew<Boolean>(true)->Value() == true));
+  t.ok(_( NanNew<Boolean>(false)->Value() == false));
+  t.ok(_( assertType<Boolean>( NanNew<Boolean>(true))));
+
+  t.ok(_( NanNew(true)->Value() == true));
+  t.ok(_( NanNew(false)->Value() == false));
+  t.ok(_( assertType<Boolean>( NanNew(true))));
+
+  return_NanUndefined();
+}
+
+#if (NODE_MODULE_VERSION < 12)
+# define V(x) x->BooleanValue()
+#else
+# define V(x) x->ValueOf()
+#endif
+NAN_METHOD(testBooleanObject) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(3);
+
+  t.ok(_( assertType<BooleanObject>( NanNew<BooleanObject>(true))));
+  t.ok(_( V(NanNew<BooleanObject>(true)) == true));
+  t.ok(_( V(NanNew<BooleanObject>(false)) == false));
+
+  return_NanUndefined();
+}
+#undef V
+
+NAN_METHOD(testContext) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(5);
+  t.ok(_( assertType<Context>( NanNew<Context>())));
+  ExtensionConfiguration extensions(0, NULL);
+  t.ok(_( assertType<Context>( NanNew<Context>(&extensions))));
+  t.ok(_( assertType<Context>(
+          NanNew<Context>(static_cast<ExtensionConfiguration *>(NULL)
+          , Handle<ObjectTemplate>()))));
+  t.ok(_( assertType<Context>(
+          NanNew<Context>(&extensions, Handle<ObjectTemplate>()))));
+  t.ok(_( assertType<Context>(
+          NanNew<Context>(&extensions
+          , Handle<ObjectTemplate>(), Handle<Value>()))));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testDate) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(1);
+
+  t.ok(_( assertType<Date>( NanNew<Date>(static_cast<double>(time(NULL))))));
+
+  return_NanUndefined();
+}
+
+int ttt = 23;
+
+NAN_METHOD(testExternal) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(2);
+
+  t.ok(_(NanNew<External>(&ttt)->Value() == &ttt));
+  t.ok(_( assertType<External>(NanNew<External>(&ttt))));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testFunction) {
+  NanScope();
+  NanTap t(args[0]);
+  t.plan(2);
+
+  t.ok(_( assertType<Function>(NanNew<Function>(testFunction))));
+  v8::Local<String> data = NanNew("plonk");
+  t.ok(_( assertType<Function>(NanNew<Function>(testFunction, data))));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testFunctionTemplate) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(4);
+
+  t.ok(_( assertType<FunctionTemplate>( NanNew<FunctionTemplate>())));
+  t.ok(_( assertType<FunctionTemplate>(
+          NanNew<FunctionTemplate>(testFunctionTemplate))));
+  v8::Local<String> data = NanNew("plonk");
+  t.ok(_( assertType<FunctionTemplate>(
+          NanNew<FunctionTemplate>( testFunctionTemplate, data))));
+  v8::Local<Signature> signature = NanNew<Signature>();
+  t.ok(_( assertType<FunctionTemplate>(
+          NanNew<FunctionTemplate>( testFunctionTemplate, data, signature))));
+
+  return_NanUndefined();
+}
+
+const double epsilon = 1e-9;
+
+NAN_METHOD(testNumber) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(17);
+
+  t.ok(_( NanNew<Int32>(5)->Value() == 5 ));
+  t.ok(_( NanNew<Int32>(-42)->Value() == -42 ));
+  t.ok(_( assertType<Int32>( NanNew<Int32>(23) )));
+
+  t.ok(_( NanNew<Uint32>(5u)->Value() == 5u ));
+  t.ok(_( assertType<Uint32>( NanNew<Uint32>(23u) )));
+
+  t.ok(_( NanNew<Integer>(5)->Value() == 5 ));
+  t.ok(_( NanNew<Integer>(-1337)->Value() == -1337 ));
+  t.ok(_( assertType<Integer>( NanNew<Integer>(-42) )));
+
+  t.ok(_( fabs(NanNew<Number>(M_PI)->Value() - M_PI) < epsilon));
+  t.ok(_( fabs(NanNew<Number>(-M_PI)->Value() + M_PI) < epsilon));
+  t.ok(_( assertType<Number>( NanNew<Number>(M_E) )));
+
+  // === Convenience
+
+  t.ok(_( NanNew(5)->Value() == 5 ));
+  t.ok(_( assertType<Int32>( NanNew(23) )));
+
+  t.ok(_( NanNew(5u)->Value() == 5u ));
+  t.ok(_( assertType<Uint32>( NanNew(23u) )));
+
+  t.ok(_( fabs(NanNew(M_PI)->Value() - M_PI) < epsilon));
+  t.ok(_( assertType<Number>( NanNew(M_E) )));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testNumberObject) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(2);
+
+  t.ok(_( assertType<NumberObject>( NanNew<NumberObject>(M_PI))));
+  t.ok(_( fabs(NanNew<NumberObject>(M_PI)->NumberValue() - M_PI) < epsilon));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testObject) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(1);
+
+  t.ok(_(assertType<Object>( NanNew<Object>())));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testObjectTemplate) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(1);
+
+  t.ok(_(assertType<ObjectTemplate>( NanNew<ObjectTemplate>())));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testScript) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(6);
+
+  ScriptOrigin origin(NanNew("foo"), NanNew(5));
+
+  t.ok(_( assertType<Script>( NanNew<Script>(NanNew("2 + 3")))));
+  t.ok(_( assertType<Script>( NanNew<Script>(NanNew("2 + 3"), origin))));
+  t.ok(_( assertType<NanUnboundScript>(
+      NanNew<NanUnboundScript>(NanNew("2 + 3")))));
+  t.ok(_( assertType<NanUnboundScript>(
+          NanNew<NanUnboundScript>(NanNew("2 + 3"), origin))));
+
+  // for the fans of the bound script
+  t.ok(_( NanRunScript(
+      NanNew<NanBoundScript>(NanNew("2 + 3")))->Int32Value() == 5));
+  t.ok(_( NanRunScript(
+      NanNew<NanUnboundScript>(NanNew("2 + 3")))->Int32Value() == 5));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testSignature) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(3);
+
+  typedef FunctionTemplate FT;
+  typedef Signature Sig;
+  t.ok(_( assertType<Sig>(NanNew<Sig>())));
+  t.ok(_( assertType<Sig>(NanNew<Sig>(NanNew<FT>(testSignature)))));
+
+  t.ok(_( assertType<Sig>(
+      NanNew<Sig>(NanNew<FT>(testSignature)))));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testString) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(14);
+
+  t.ok(_( stringMatches( NanNew<String>("Hello World"), "Hello World")));
+  t.ok(_( stringMatches( NanNew<String>("Hello World", 4), "Hell")));
+  t.ok(_( stringMatches( NanNew<String>(std::string("foo")), "foo")));
+  t.ok(_( assertType<String>( NanNew<String>("plonk."))));
+
+  t.ok(_( stringMatches( NanNew<String>(), "")));
+  t.ok(_( assertType<String>( NanNew<String>())));
+
+  // These should be deprecated
+  const uint8_t *ustring = reinterpret_cast<const uint8_t *>("unsigned chars");
+  t.ok(_( stringMatches( NanNew<String>(ustring), "unsigned chars")));
+  t.ok(_( stringMatches( NanNew<String>(ustring, 8), "unsigned")));
+
+  // === Convenience
+
+  t.ok(_( stringMatches( NanNew("using namespace nan; // is poetry"),
+          "using namespace nan; // is poetry")));
+  t.ok(_( assertType<String>( NanNew("plonk."))));
+
+  t.ok(_( stringMatches( NanNew("Hello World", 4), "Hell")));
+  t.ok(_( assertType<String>( NanNew("plonk.", 4))));
+
+  t.ok(_( stringMatches( NanNew(std::string("bar")), "bar")));
+  t.ok(_( assertType<String>( NanNew(std::string("plonk.")))));
+
+  return_NanUndefined();
+}
+
+#if (NODE_MODULE_VERSION < 12)
+# define V(x) x->StringValue()
+#else
+# define V(x) x->ValueOf()
+#endif
+NAN_METHOD(testStringObject) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(2);
+
+  t.ok(_( stringMatches(
+          V(NanNew<StringObject>(NanNew<String>("plonk"))),
+          "plonk")));
+  t.ok(_( assertType<StringObject>(
+          NanNew<StringObject>(NanNew<String>("plonk")))));
+
+  return_NanUndefined();
+}
+#undef V
+
+template <typename T> Handle<T> asHandle(Local<T> l) { return l; }
+NAN_METHOD(testHandles) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(2);
+
+  t.ok(_( assertType<String>( NanNew( asHandle(NanNew("foo"))))));
+  t.ok(_( assertType<Uint32>( NanNew( asHandle(NanNew(5u))))));
+
+  return_NanUndefined();
+}
+
+NAN_METHOD(testPersistents) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(1);
+
+  Persistent<String> p;
+  NanAssignPersistent(p, NanNew("foo"));
+  t.ok(_( assertType<String>( NanNew(p))));
+  NanDisposePersistent(p);
+
+  return_NanUndefined();
+}
+
+//==============================================================================
+// Regression Tests
+//==============================================================================
+
+
+// See https://github.com/rvagg/nan/issues/212
+NAN_METHOD(testRegression212) {
+  NanScope();
+  NanTap t(args[0]);
+
+  t.plan(1);
+
+  typedef int  gint;
+  typedef gint gboolean;
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4800 )
+#endif
+  t.ok(_( assertType<Boolean>( NanNew<Boolean>(gboolean(23)))));
+#if defined(_MSC_VER)
+# pragma warning( pop )
+#endif
+
+  return_NanUndefined();
+}
+
+/* Compile time regression test for https://github.com/rvagg/nan/issues/242
+ * In the presence of overloaded functions NaN should be able to pick the one
+ * matching NanFunctionCallback.
+ */
+void overloaded() {}
+NAN_METHOD(overloaded) {
+    overloaded();  // not unused
+    return_NanUndefined();
+}
+
+NAN_METHOD(testRegression242) {
+  NanScope();
+  NanTap t(args[0]);
+
+  // These lines must *compile*. Not much to test at runtime.
+  Local<FunctionTemplate> ft = NanNew<FunctionTemplate>(overloaded);
+  (void)ft;  // not unused
+  Local<Function> f = NanNew<Function>(overloaded);
+  (void)f;  // not unused
+
+  t.plan(1);
+
+  t.ok(true, "compile-time regression test #242");
+
+  return_NanUndefined();
+}
+
+
+//==============================================================================
+// JavaScript Tests
+//==============================================================================
+
+NAN_METHOD(newIntegerWithValue) {
+  NanScope();
+  return_NanValue(NanNew<Integer>(args[0]->Int32Value()));
+}
+
+NAN_METHOD(newNumberWithValue) {
+  NanScope();
+  return_NanValue(NanNew<Number>(args[0]->NumberValue()));
+}
+
+NAN_METHOD(newUint32WithValue) {
+  NanScope();
+  return_NanValue(NanNew<Uint32>(args[0]->Uint32Value()));
+}
+
+NAN_METHOD(newStringFromChars) {
+  NanScope();
+  return_NanValue(NanNew<String>("hello?"));
+}
+
+NAN_METHOD(newStringFromCharsWithLength) {
+  NanScope();
+  return_NanValue(NanNew<String>("hello?", 4));
+}
+
+NAN_METHOD(newStringFromStdString) {
+  NanScope();
+  return_NanValue(NanNew<String>(std::string("hello!")));
+}
+
+NAN_METHOD(newExternal) {
+  NanScope();
+  return_NanValue(NanNew<External>(&ttt));
+}
+
+void Init(Handle<Object> exports) {
+  NAN_EXPORT(exports, testArray);
+  NAN_EXPORT(exports, testBoolean);
+  NAN_EXPORT(exports, testBooleanObject);
+  NAN_EXPORT(exports, testContext);
+  NAN_EXPORT(exports, testDate);
+  NAN_EXPORT(exports, testExternal);
+  NAN_EXPORT(exports, testFunction);
+  NAN_EXPORT(exports, testFunctionTemplate);
+  NAN_EXPORT(exports, testNumber);
+  NAN_EXPORT(exports, testNumberObject);
+  NAN_EXPORT(exports, testObject);
+  NAN_EXPORT(exports, testObjectTemplate);
+  NAN_EXPORT(exports, testScript);
+  NAN_EXPORT(exports, testSignature);
+  NAN_EXPORT(exports, testString);
+  NAN_EXPORT(exports, testStringObject);
+
+  NAN_EXPORT(exports, testHandles);
+  NAN_EXPORT(exports, testPersistents);
+
+  NAN_EXPORT(exports, testRegression212);
+  NAN_EXPORT(exports, testRegression242);
+
+  NAN_EXPORT(exports, newIntegerWithValue);
+  NAN_EXPORT(exports, newNumberWithValue);
+  NAN_EXPORT(exports, newUint32WithValue);
+  NAN_EXPORT(exports, newStringFromChars);
+  NAN_EXPORT(exports, newStringFromCharsWithLength);
+  NAN_EXPORT(exports, newStringFromStdString);
+
+  NAN_EXPORT(exports, newExternal);
+}
+
+}  // end of anonymous namespace
+
+NODE_MODULE(nannew, Init)
diff --git a/test/cpp/news.cpp b/test/cpp/news.cpp
index 488fc21..29ec132 100644
--- a/test/cpp/news.cpp
+++ b/test/cpp/news.cpp
@@ -1,13 +1,20 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
-#include <string>
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4530 )
+# include <string>
+# pragma warning( pop )
+#else
+# include <string>
+#endif
 
 static int magic = 1337;
 
@@ -26,6 +33,11 @@ NAN_METHOD(NewPositiveInteger) {
   NanReturnValue(NanNew<v8::Integer>(1));
 }
 
+NAN_METHOD(NewUnsignedInteger) {
+  NanScope();
+  NanReturnValue(NanNew<v8::Integer>(0xFFFFFFFFu));
+}
+
 NAN_METHOD(NewInt32FromPositive) {
   NanScope();
   NanReturnValue(NanNew<v8::Int32>(0xFFFFFFFF));
@@ -101,7 +113,7 @@ NAN_METHOD(NewSignature) {
   NanScope();
   v8::Local<v8::FunctionTemplate> tmpl =
       NanNew<v8::FunctionTemplate>(NewSignature);
-  v8::Local<v8::Signature> sig = NanNew<v8::Signature>(tmpl, 1, &tmpl);
+  v8::Local<v8::Signature> sig = NanNew<v8::Signature>(tmpl);
   tmpl = NanNew<v8::FunctionTemplate>(
       NewSignature, v8::Handle<v8::Value>(), sig);
   NanReturnValue(NanNew<v8::String>("string"));
@@ -144,6 +156,26 @@ NAN_METHOD(NewArray) {
   NanReturnValue(NanNew<v8::Array>());
 }
 
+NAN_METHOD(NewBoolean) {
+  NanScope();
+  NanReturnValue(NanNew<v8::Boolean>(true));
+}
+
+// #212
+NAN_METHOD(NewBoolean2) {
+  NanScope();
+
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4800 )
+#endif
+  NanReturnValue(NanNew<v8::Boolean>(1));
+#if defined(_MSC_VER)
+# pragma warning( pop )
+#endif
+
+}
+
 void Init(v8::Handle<v8::Object> target) {
   target->Set(
       NanNew<v8::String>("newNumber")
@@ -158,6 +190,10 @@ void Init(v8::Handle<v8::Object> target) {
     , NanNew<v8::FunctionTemplate>(NewPositiveInteger)->GetFunction()
   );
   target->Set(
+      NanNew<v8::String>("newUnsignedInteger")
+    , NanNew<v8::FunctionTemplate>(NewUnsignedInteger)->GetFunction()
+  );
+  target->Set(
       NanNew<v8::String>("newInt32FromPositive")
     , NanNew<v8::FunctionTemplate>(NewInt32FromPositive)->GetFunction()
   );
@@ -237,6 +273,14 @@ void Init(v8::Handle<v8::Object> target) {
       NanNew<v8::String>("newArray")
     , NanNew<v8::FunctionTemplate>(NewArray)->GetFunction()
   );
+  target->Set(
+      NanNew<v8::String>("newBoolean")
+    , NanNew<v8::FunctionTemplate>(NewBoolean)->GetFunction()
+  );
+  target->Set(
+      NanNew<v8::String>("newBoolean2")
+    , NanNew<v8::FunctionTemplate>(NewBoolean2)->GetFunction()
+  );
 }
 
 NODE_MODULE(news, Init)
diff --git a/test/cpp/objectwraphandle.cpp b/test/cpp/objectwraphandle.cpp
new file mode 100644
index 0000000..d4a26ac
--- /dev/null
+++ b/test/cpp/objectwraphandle.cpp
@@ -0,0 +1,61 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#include <nan.h>
+
+class MyObject : public node::ObjectWrap {
+ public:
+  static void Init(v8::Handle<v8::Object> exports) {
+    NanScope();
+    v8::Local<v8::FunctionTemplate> tpl = NanNew<v8::FunctionTemplate>(New);
+    tpl->SetClassName(NanNew("MyObject"));
+    tpl->InstanceTemplate()->SetInternalFieldCount(1);
+
+    NODE_SET_PROTOTYPE_METHOD(tpl, "getHandle", GetHandle);
+
+    NanAssignPersistent(constructor, tpl->GetFunction());
+    exports->Set(NanNew("MyObject"), tpl->GetFunction());
+  }
+
+ private:
+  explicit MyObject(double value=0) : value_(value) {}
+  ~MyObject() {}
+
+  static NAN_METHOD(New) {
+    NanScope();
+
+    if (args.IsConstructCall()) {
+      double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
+      MyObject *obj = new MyObject(value);
+      obj->Wrap(args.This());
+      NanReturnThis();
+    } else {
+      const int argc = 1;
+      v8::Local<v8::Value> argv[argc] = {args[0]};
+      v8::Local<v8::Function> cons = NanNew(constructor);
+      NanReturnValue(cons->NewInstance(argc, argv));
+    }
+  }
+
+  static NAN_METHOD(GetHandle) {
+    NanScope();
+    MyObject* obj = node::ObjectWrap::Unwrap<MyObject>(args.This());
+    NanReturnValue(NanObjectWrapHandle(obj));
+  }
+
+  static v8::Persistent<v8::Function> constructor;
+  double value_;
+};
+
+v8::Persistent<v8::Function> MyObject::constructor;
+
+void Init(v8::Handle<v8::Object> exports) {
+  MyObject::Init(exports);
+}
+
+NODE_MODULE(objectwraphandle, Init)
diff --git a/test/cpp/optionvalues.cpp b/test/cpp/optionvalues.cpp
index f8ee7eb..287c58f 100644
--- a/test/cpp/optionvalues.cpp
+++ b/test/cpp/optionvalues.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/persistent.cpp b/test/cpp/persistent.cpp
index cd847d8..a5414ed 100644
--- a/test/cpp/persistent.cpp
+++ b/test/cpp/persistent.cpp
@@ -1,13 +1,13 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
-#include <string.h>  // memset()
+#include <cstring>  // memset()
 
 static v8::Persistent<v8::String> persistentTest1;
 
diff --git a/test/cpp/returnemptystring.cpp b/test/cpp/returnemptystring.cpp
index 3bb4f1f..29cfaa8 100644
--- a/test/cpp/returnemptystring.cpp
+++ b/test/cpp/returnemptystring.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/returnnull.cpp b/test/cpp/returnnull.cpp
index 64dfbf8..cbb3ac3 100644
--- a/test/cpp/returnnull.cpp
+++ b/test/cpp/returnnull.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/returnundefined.cpp b/test/cpp/returnundefined.cpp
index d019e95..6bb7a17 100644
--- a/test/cpp/returnundefined.cpp
+++ b/test/cpp/returnundefined.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/returnvalue.cpp b/test/cpp/returnvalue.cpp
index 94514fe..b244157 100644
--- a/test/cpp/returnvalue.cpp
+++ b/test/cpp/returnvalue.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
@@ -17,11 +17,29 @@ NAN_METHOD(ReturnValue) {
   }
 }
 
+NAN_METHOD(ReturnPrimitive) {
+  NanScope();
+  NanReturnValue(true);
+}
+
+NAN_METHOD(ReturnString) {
+  NanScope();
+  NanReturnValue("yes, it works");
+}
+
 void Init (v8::Handle<v8::Object> target) {
   target->Set(
       NanNew<v8::String>("r")
     , NanNew<v8::FunctionTemplate>(ReturnValue)->GetFunction()
   );
+  target->Set(
+      NanNew<v8::String>("p")
+    , NanNew<v8::FunctionTemplate>(ReturnPrimitive)->GetFunction()
+  );
+  target->Set(
+      NanNew<v8::String>("s")
+    , NanNew<v8::FunctionTemplate>(ReturnString)->GetFunction()
+  );
 }
 
 NODE_MODULE(returnvalue, Init)
diff --git a/test/cpp/settemplate.cpp b/test/cpp/settemplate.cpp
index 2845d57..e062270 100644
--- a/test/cpp/settemplate.cpp
+++ b/test/cpp/settemplate.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
-* NAN - Native Abstractions for Node.js
-*
-* Copyright (c) 2014 NAN contributors
-*
-* MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
-**********************************************************************************/
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/settergetter.cpp b/test/cpp/settergetter.cpp
index 8fb44d9..bf0c6dd 100644
--- a/test/cpp/settergetter.cpp
+++ b/test/cpp/settergetter.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 #include <cstring>
diff --git a/test/cpp/strings.cpp b/test/cpp/strings.cpp
index 84630c8..a1f217d 100644
--- a/test/cpp/strings.cpp
+++ b/test/cpp/strings.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
@@ -31,10 +31,22 @@ NAN_METHOD(HeapString) {
   NanReturnValue(res);
 }
 
+NAN_METHOD(EncodeHex) {
+  NanScope();
+  NanReturnValue(NanEncode("hello", 5, Nan::HEX));
+}
+
+NAN_METHOD(EncodeUCS2) {
+  NanScope();
+  NanReturnValue(NanEncode("h\0e\0l\0l\0o\0", 10, Nan::UCS2));
+}
+
 v8::Persistent<v8::FunctionTemplate> returnAsciiString_persistent;
 v8::Persistent<v8::FunctionTemplate> returnUtf8String_persistent;
 v8::Persistent<v8::FunctionTemplate> returnUcs2String_persistent;
 v8::Persistent<v8::FunctionTemplate> heapString_persistent;
+v8::Persistent<v8::FunctionTemplate> encodeHex_persistent;
+v8::Persistent<v8::FunctionTemplate> encodeUCS2_persistent;
 
 void Init (v8::Handle<v8::Object> target) {
   NanScope();
@@ -90,6 +102,32 @@ void Init (v8::Handle<v8::Object> target) {
       NanNew("heapString")
     , heapString->GetFunction()
   );
+
+  v8::Local<v8::FunctionTemplate> encodeHex =
+    NanNew<v8::FunctionTemplate>(EncodeHex);
+
+  NanAssignPersistent(
+    encodeHex_persistent
+  , encodeHex
+  );
+
+  target->Set(
+      NanNew("encodeHex")
+    , encodeHex->GetFunction()
+  );
+
+  v8::Local<v8::FunctionTemplate> encodeUCS2 =
+    NanNew<v8::FunctionTemplate>(EncodeUCS2);
+
+  NanAssignPersistent(
+    encodeUCS2_persistent
+  , encodeUCS2
+  );
+
+  target->Set(
+      NanNew("encodeUCS2")
+    , encodeUCS2->GetFunction()
+  );
 }
 
 NODE_MODULE(strings, Init)
diff --git a/test/cpp/symbols.cpp b/test/cpp/symbols.cpp
index 6760373..ffe555d 100644
--- a/test/cpp/symbols.cpp
+++ b/test/cpp/symbols.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/cpp/threadlocal.cpp b/test/cpp/threadlocal.cpp
new file mode 100644
index 0000000..2498cc2
--- /dev/null
+++ b/test/cpp/threadlocal.cpp
@@ -0,0 +1,68 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#include <nan.h>
+
+#define _(e) NAN_TEST_EXPRESSION(e)
+
+// Based on test-thread.c from libuv.
+
+class TlsTest : public NanAsyncWorker {
+public:
+  TlsTest(NanTap *t) : NanAsyncWorker(NULL), t(t), i(0) {
+    NanScope();
+    t->plan(7);
+    t->ok(_(0 == nauv_key_create(&tls_key)));
+    t->ok(_(NULL == nauv_key_get(&tls_key)));
+    nauv_key_set(&tls_key, this);
+    t->ok(_(this == nauv_key_get(&tls_key)));
+  }
+  void Execute() {
+    ok(_(NULL == nauv_key_get(&tls_key)));
+    nauv_key_set(&tls_key, &i);
+    ok(_(&i == nauv_key_get(&tls_key)));
+    nauv_key_set(&tls_key, NULL);
+    ok(_(NULL == nauv_key_get(&tls_key)));
+  }
+  void WorkComplete() {
+    NanScope();
+    for (unsigned j = 0; j < i; ++j)
+      t->ok(res[j].ok, res[j].msg);
+    nauv_key_delete(&tls_key);
+    t->ok(_(NULL == ErrorMessage()));
+    delete t;
+  }
+private:
+  nauv_key_t tls_key;
+
+  NanTap *t;
+  struct { bool ok; const char* msg; } res[3];
+  unsigned i;
+  void ok(bool isOk, const char *msg) {
+    assert(i < sizeof(res)/sizeof(res[0]));
+    res[i].ok = isOk;
+    res[i].msg = msg;
+    ++i;
+  }
+};
+
+NAN_METHOD(thread_local_storage) {
+  NanScope();
+  NanTap *t = new NanTap(args[0]);
+  NanAsyncQueueWorker(new TlsTest(t));
+  return_NanUndefined();
+}
+
+void Init(v8::Handle<v8::Object> exports) {
+  exports->Set(
+      NanNew<v8::String>("thread_local_storage")
+    , NanNew<v8::FunctionTemplate>(thread_local_storage)->GetFunction()
+  );
+}
+
+NODE_MODULE(threadlocal, Init)
diff --git a/test/cpp/weak.cpp b/test/cpp/weak.cpp
index eb0e16d..e8b471b 100644
--- a/test/cpp/weak.cpp
+++ b/test/cpp/weak.cpp
@@ -1,10 +1,10 @@
-/**********************************************************************************
+/*********************************************************************
  * NAN - Native Abstractions for Node.js
  *
- * Copyright (c) 2014 NAN contributors
+ * Copyright (c) 2015 NAN contributors
  *
- * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
- **********************************************************************************/
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
 
 #include <nan.h>
 
diff --git a/test/js/asyncprogressworker-test.js b/test/js/asyncprogressworker-test.js
new file mode 100644
index 0000000..18df205
--- /dev/null
+++ b/test/js/asyncprogressworker-test.js
@@ -0,0 +1,23 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+const test     = require('tap').test
+    , testRoot = require('path').resolve(__dirname, '..')
+    , bindings = require('bindings')({ module_root: testRoot, bindings: 'asyncprogressworker' });
+
+test('asyncprogressworker', function (t) {
+  var worker = bindings.a
+    , progressed = 0
+  worker(100, 5, function(i) {
+    t.ok(i === progressed, 'got the progress updates #' + i);
+    progressed++;
+  }, function () {
+    t.ok(progressed === 5, 'got all progress updates')
+    t.end()
+  })
+})
diff --git a/test/js/asyncworker-test.js b/test/js/asyncworker-test.js
index 054b2d9..9eb08c2 100644
--- a/test/js/asyncworker-test.js
+++ b/test/js/asyncworker-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'asyncworker' });
diff --git a/test/js/asyncworkererror-test.js b/test/js/asyncworkererror-test.js
index c5462d8..524297f 100644
--- a/test/js/asyncworkererror-test.js
+++ b/test/js/asyncworkererror-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'asyncworkererror' });
diff --git a/test/js/bufferworkerpersistent-test.js b/test/js/bufferworkerpersistent-test.js
index 1efc9a0..90af9a3 100644
--- a/test/js/bufferworkerpersistent-test.js
+++ b/test/js/bufferworkerpersistent-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'bufferworkerpersistent' })
diff --git a/test/js/gc-test.js b/test/js/gc-test.js
new file mode 100644
index 0000000..176ee0e
--- /dev/null
+++ b/test/js/gc-test.js
@@ -0,0 +1,23 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+const test     = require('tap').test
+    , testRoot = require('path').resolve(__dirname, '..')
+    , bindings = require('bindings')({ module_root: testRoot, bindings: 'gc' });
+
+test('gc', function (t) {
+  t.plan(3);
+
+  t.type(bindings.hook, 'function');
+
+  bindings.hook(function (from) {
+    t.ok(from == 'prologue' || from == 'epilogue');
+  });
+
+  gc();
+});
diff --git a/test/js/isolatedata-test.js b/test/js/isolatedata-test.js
index e5637ef..1d0de44 100644
--- a/test/js/isolatedata-test.js
+++ b/test/js/isolatedata-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'isolatedata' });
diff --git a/test/js/makecallback-test.js b/test/js/makecallback-test.js
index b6e3607..bbd5a83 100644
--- a/test/js/makecallback-test.js
+++ b/test/js/makecallback-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , MyObject = require('bindings')({ module_root: testRoot, bindings: 'makecallback' }).MyObject
diff --git a/test/js/morenews-test.js b/test/js/morenews-test.js
index 47a580c..9a85595 100644
--- a/test/js/morenews-test.js
+++ b/test/js/morenews-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'morenews' });
diff --git a/test/js/multifile-test.js b/test/js/multifile-test.js
index a9b17c9..bda51ea 100644
--- a/test/js/multifile-test.js
+++ b/test/js/multifile-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'multifile' });
diff --git a/test/js/nancallback-test.js b/test/js/nancallback-test.js
new file mode 100644
index 0000000..d0b64dc
--- /dev/null
+++ b/test/js/nancallback-test.js
@@ -0,0 +1,30 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+const test     = require('tap').test
+    , testRoot = require('path').resolve(__dirname, '..')
+    , bindings = require('bindings')({ module_root: testRoot, bindings: 'nancallback' })
+    , round = Math.round;
+
+test('nancallback', function (t) {
+  t.plan(7)
+
+  var persistent = bindings;
+  t.type(persistent.globalContext, 'function');
+  t.type(persistent.specificContext, 'function');
+  t.type(persistent.compareCallbacks, 'function');
+  persistent.globalContext(function () { t.ok(true); });
+  persistent.specificContext(function () { t.ok(true); });
+
+  var round2 = Math.round
+    , x = function(param) { return param + 1; }
+    , y = function(param) { return param + 2; }
+    , x2 = x;
+  t.ok(persistent.compareCallbacks(round, round2, Math.floor));
+  t.ok(persistent.compareCallbacks(x, x2, y));
+})
diff --git a/test/js/nannew-test.js b/test/js/nannew-test.js
new file mode 100644
index 0000000..2358a9e
--- /dev/null
+++ b/test/js/nannew-test.js
@@ -0,0 +1,51 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+const test     = require('tap').test
+    , testRoot = require('path').resolve(__dirname, '..')
+    , bindings = require('bindings')({ module_root: testRoot, bindings: 'nannew' });
+
+
+// register c++ functions as tests...
+for (var symbol in bindings) {
+  if (typeof bindings[symbol] == 'function' && symbol.match(/^test.*/)) {
+    test('C++: ' + symbol, bindings[symbol]);
+  }
+}
+
+test('numbers', function (t) {
+  t.plan(12);
+
+  t.type(bindings.newIntegerWithValue, 'function');
+  t.equals(bindings.newIntegerWithValue(23), 23);
+  t.equals(bindings.newIntegerWithValue(5), 5);
+  t.type(bindings.newIntegerWithValue(23), 'number');
+
+  t.type(bindings.newNumberWithValue, 'function');
+  t.equals(bindings.newNumberWithValue(Math.PI), Math.PI);
+  t.equals(bindings.newNumberWithValue(Math.E), Math.E);
+  t.type(bindings.newNumberWithValue(Math.PI), 'number');
+
+  t.type(bindings.newUint32WithValue, 'function');
+  t.equals(bindings.newUint32WithValue(23), 23);
+  t.equals(bindings.newUint32WithValue(5), 5);
+  t.type(bindings.newUint32WithValue(5), 'number');
+  t.end();
+});
+
+
+test('strings', function (t) {
+  t.plan(3);
+
+  t.equals(bindings.newStringFromChars(), "hello?");
+  t.equals(bindings.newStringFromCharsWithLength(), "hell");
+  t.equals(bindings.newStringFromStdString(), "hello!");
+
+  t.end();
+});
+
diff --git a/test/js/news-test.js b/test/js/news-test.js
index ffdfb51..9be5b07 100644
--- a/test/js/news-test.js
+++ b/test/js/news-test.js
@@ -1,12 +1,21 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'news' });
 
 test('news', function (t) {
-  t.plan(46);
+  t.plan(52);
   t.type(bindings.newNumber, 'function');
   t.type(bindings.newPositiveInteger, 'function');
   t.type(bindings.newNegativeInteger, 'function');
+  t.type(bindings.newUnsignedInteger, 'function');
   t.type(bindings.newInt32FromPositive, 'function');
   t.type(bindings.newInt32FromNegative, 'function');
   t.type(bindings.newUint32FromPositive, 'function');
@@ -27,10 +36,13 @@ test('news', function (t) {
   t.type(bindings.compileScript2, 'function');
   t.type(bindings.newDate, 'function');
   t.type(bindings.newArray, 'function');
+  t.type(bindings.newBoolean, 'function');
+  t.type(bindings.newBoolean2, 'function');
 
   t.equal(bindings.newNumber(), 0.5);
   t.equal(bindings.newPositiveInteger(), 1);
   t.equal(bindings.newNegativeInteger(), -1);
+  t.equal(bindings.newUnsignedInteger(), 0xFFFFFFFF);
   t.equal(bindings.newInt32FromPositive(), -1);
   t.equal(bindings.newInt32FromNegative(), -1);
   t.equal(bindings.newUint32FromPositive(), 0xFFFFFFFF);
@@ -51,4 +63,6 @@ test('news', function (t) {
   t.equals(bindings.compileScript2(), 6);
   t.deepEquals(bindings.newDate(), new Date(1337));
   t.deepEquals(bindings.newArray(), []);
+  t.equal(bindings.newBoolean(), true);
+  t.equal(bindings.newBoolean2(), true);
 });
diff --git a/test/js/objectwraphandle-test.js b/test/js/objectwraphandle-test.js
new file mode 100644
index 0000000..0dafcec
--- /dev/null
+++ b/test/js/objectwraphandle-test.js
@@ -0,0 +1,22 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+const test     = require('tap').test
+    , testRoot = require('path').resolve(__dirname, '..')
+    , bindings = require('bindings')({ module_root: testRoot, bindings: 'objectwraphandle' });
+
+test('objectwraphandle', function (t) {
+  t.plan(3);
+
+  t.type(bindings.MyObject, 'function');
+
+  var obj = new bindings.MyObject(10);
+
+  t.type(obj.getHandle, 'function');
+  t.type(obj.getHandle(), 'object');
+});
diff --git a/test/js/optionvalues-test.js b/test/js/optionvalues-test.js
index 3fd8bf8..3ddfdb4 100644
--- a/test/js/optionvalues-test.js
+++ b/test/js/optionvalues-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'optionvalues' })
diff --git a/test/js/persistent-test.js b/test/js/persistent-test.js
index 16c6692..5d54553 100644
--- a/test/js/persistent-test.js
+++ b/test/js/persistent-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'persistent' });
diff --git a/test/js/returnemptystring-test.js b/test/js/returnemptystring-test.js
index 1be1edb..30c7b12 100644
--- a/test/js/returnemptystring-test.js
+++ b/test/js/returnemptystring-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'returnemptystring' });
diff --git a/test/js/returnnull-test.js b/test/js/returnnull-test.js
index db2d596..e6a80ae 100644
--- a/test/js/returnnull-test.js
+++ b/test/js/returnnull-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'returnnull' });
diff --git a/test/js/returnundefined-test.js b/test/js/returnundefined-test.js
index ab1549f..7325e64 100644
--- a/test/js/returnundefined-test.js
+++ b/test/js/returnundefined-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'returnundefined' });
diff --git a/test/js/returnvalue-test.js b/test/js/returnvalue-test.js
index b2a3034..6c7741c 100644
--- a/test/js/returnvalue-test.js
+++ b/test/js/returnvalue-test.js
@@ -1,10 +1,22 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'returnvalue' });
 
 test('returnvalue', function (t) {
-  t.plan(3);
+  t.plan(7);
   t.type(bindings.r, 'function');
+  t.type(bindings.p, 'function');
+  t.type(bindings.s, 'function');
   t.equal(bindings.r('a string value'), 'a string value');
   t.equal(bindings.r(), 'default');
+  t.ok(bindings.p());
+  t.equal(bindings.s(), 'yes, it works');
 });
diff --git a/test/js/settemplate-test.js b/test/js/settemplate-test.js
index 9f691f0..a5e126a 100644
--- a/test/js/settemplate-test.js
+++ b/test/js/settemplate-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'settemplate' })
diff --git a/test/js/settergetter-test.js b/test/js/settergetter-test.js
index 953bcdf..b5899a0 100644
--- a/test/js/settergetter-test.js
+++ b/test/js/settergetter-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'settergetter' });
diff --git a/test/js/strings-test.js b/test/js/strings-test.js
index 76acba1..796b077 100644
--- a/test/js/strings-test.js
+++ b/test/js/strings-test.js
@@ -1,10 +1,18 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'strings' });
 
 
 test('FromV8String', function (t) {
-  t.plan(8);
+  t.plan(10);
 
   var a = bindings.returnAsciiString;
   var b = bindings.returnUtf8String;
@@ -20,4 +28,7 @@ test('FromV8String', function (t) {
   t.equal(b('an utf8 strïng'), 'an utf8 strïng');
   t.equal(c('an ucs2 strïng'), 'an ucs2 strïng');
   t.equal(d('an utf8 strïng'), 'an utf8 strïng');
+
+  t.equal(bindings.encodeHex(), new Buffer('hello').toString('hex'));
+  t.equal(bindings.encodeUCS2(), 'hello');
 });
diff --git a/test/js/symbols-test.js b/test/js/symbols-test.js
index eaf3eb6..7e06670 100644
--- a/test/js/symbols-test.js
+++ b/test/js/symbols-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'symbols' });
diff --git a/test/js/threadlocal-test.js b/test/js/threadlocal-test.js
new file mode 100644
index 0000000..4f1105c
--- /dev/null
+++ b/test/js/threadlocal-test.js
@@ -0,0 +1,13 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+const test     = require('tap').test
+    , testRoot = require('path').resolve(__dirname, '..')
+    , bindings = require('bindings')({ module_root: testRoot, bindings: 'threadlocal' });
+
+test('thread local storage', bindings.thread_local_storage);
diff --git a/test/js/weak-test.js b/test/js/weak-test.js
index 4c0badc..dacfd5b 100644
--- a/test/js/weak-test.js
+++ b/test/js/weak-test.js
@@ -1,3 +1,11 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2015 NAN contributors
+ *
+ * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
 const test     = require('tap').test
     , testRoot = require('path').resolve(__dirname, '..')
     , bindings = require('bindings')({ module_root: testRoot, bindings: 'weak' });

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-nan.git



More information about the Pkg-javascript-commits mailing list