pax_global_header00006660000000000000000000000064135725674410014530gustar00rootroot0000000000000052 comment=039ea03bd3554fd5e6b913dcd059a3dd113ba957 node-re2-1.10.5/000077500000000000000000000000001357256744100132275ustar00rootroot00000000000000node-re2-1.10.5/.editorconfig000066400000000000000000000003061357256744100157030ustar00rootroot00000000000000root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true indent_style = space indent_size = 2 [*.{h,cc,cpp}] indent_style = tab indent_size = 4 node-re2-1.10.5/.gitignore000066400000000000000000000001431357256744100152150ustar00rootroot00000000000000node_modules/ build/ report/ coverage/ .AppleDouble vendor/* !vendor/re2/* !vendor/util/* .vscode/ node-re2-1.10.5/.gitmodules000066400000000000000000000001111357256744100153750ustar00rootroot00000000000000[submodule "vendor"] path = vendor url = https://github.com/google/re2 node-re2-1.10.5/.prettierrc000066400000000000000000000001121357256744100154050ustar00rootroot00000000000000{ "printWidth": 160, "singleQuote": true, "bracketSpacing": false } node-re2-1.10.5/.travis.yml000066400000000000000000000006161357256744100153430ustar00rootroot00000000000000sudo: false language: node_js node_js: - "8" - "10" - "12" - "13" addons: apt: sources: - ubuntu-toolchain-r-test packages: - build-essential - gcc-7 - g++-7 before_install: - export CXX="g++-7" before_script: - if [ "`nvm current`" < "system" ]; then N=`which node`; D=`dirname $N`; ln -s $D/../lib/node_modules/npm/bin/node-gyp-bin/node-gyp; fi node-re2-1.10.5/LICENSE000066400000000000000000000035651357256744100142450ustar00rootroot00000000000000This library is available under the terms of the modified BSD license. No external contributions are allowed under licenses which are fundamentally incompatible with the BSD license that this library is distributed under. The text of the BSD license is reproduced below. ------------------------------------------------------------------------------- The "New" BSD License: ********************** Copyright (c) 2005-2014, Eugene Lazutkin All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Eugene Lazutkin nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. node-re2-1.10.5/README.md000066400000000000000000000415341357256744100145150ustar00rootroot00000000000000# node-re2 [![NPM version][npm-image]][npm-url] [![Greenkeeper badge](https://badges.greenkeeper.io/uhop/node-re2.svg)](https://greenkeeper.io/) [![Dependencies][deps-image]][deps-url] [![devDependencies][dev-deps-image]][dev-deps-url] This project provides bindings for [RE2](https://github.com/google/re2): fast, safe alternative to backtracking regular expression engines written by [Russ Cox](http://swtch.com/~rsc/). To learn more about RE2, start with an overview [Regular Expression Matching in the Wild](http://swtch.com/~rsc/regexp/regexp3.html). More resources can be found at his [Implementing Regular Expressions](http://swtch.com/~rsc/regexp/) page. `RE2`'s regular expression language is almost a superset of what is provided by `RegExp` (see [Syntax](https://github.com/google/re2/wiki/Syntax)), but it lacks two features: backreferences and lookahead assertions. See below for more details. `RE2` object emulates standard `RegExp` making it a practical drop-in replacement in most cases. `RE2` is extended to provide `String`-based regular expression methods as well. To help converting `RegExp` objects to `RE2` its constructor can take `RegExp` directly honoring all properties. It can work with [node.js buffers](http://nodejs.org/api/buffer.html) directly reducing overhead on recoding and copying characters, and making processing/parsing long files fast. ## Why use node-re2? The built-in Node.js regular expression engine can run in exponential time with a special combination: - A vulnerable regular expression - "Evil input" This can lead to what is known as a [Regular Expression Denial of Service (ReDoS)](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). To tell if your regular expressions are vulnerable, you might try the one of these projects: - [rxxr2](http://www.cs.bham.ac.uk/~hxt/research/rxxr2/) - [safe-regex](https://github.com/substack/safe-regex) However, neither project is perfect. node-re2 can protect your Node.js application from ReDoS. node-re2 makes vulnerable regular expression patterns safe by evaluating them in `RE2` instead of the built-in Node.js regex engine. ## Standard features `RE2` object can be created just like `RegExp`: * [`new RE2(pattern[, flags])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) Supported properties: * [`re2.lastIndex`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex) * [`re2.global`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/global) * [`re2.ignoreCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/ignoreCase) * [`re2.multiline`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/multiline) * [`re2.unicode`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode) * `RE2` engine always works in the Unicode mode. See details below. * [`re2.sticky`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky) * [`re2.source`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source) * [`re2.flags`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags) Supported methods: * [`re2.exec(str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec) * [`re2.test(str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test) * [`re2.toString()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString) Starting with 1.6.0 following well-known symbol-based methods are supported (see [Symbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)): * [`re2[Symbol.match](str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/match) * [`re2[Symbol.search](str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/search) * [`re2[Symbol.replace](str, newSubStr|function)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/replace) * [`re2[Symbol.split](str[, limit])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/split) It allows to use `RE2` instances on strings directly, just like `RegExp` instances: ```js var re = new RE2("1"); "213".match(re); // [ '1', index: 1, input: '213' ] "213".search(re); // 1 "213".replace(re, "+"); // 2+3 "213".split(re); // [ '2', '3' ] ``` Starting with 1.8.0 [named groups](https://tc39.github.io/proposal-regexp-named-groups/) are supported. ## Extensions ### Shortcut construction `RE2` object can be created from a regular expression: ```js var re1 = new RE2(/ab*/ig); // from a RegExp object var re2 = new RE2(re1); // from another RE2 object ``` ### `String` methods Standard `String` defines four more methods that can use regular expressions. `RE2` provides them as methods exchanging positions of a string, and a regular expression: * `re2.match(str)` * See [`str.match(regexp)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match) * `re2.replace(str, newSubStr|function)` * See [`str.replace(regexp, newSubStr|function)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace) * `re2.search(str)` * See [`str.search(regexp)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search) * `re2.split(str[, limit])` * See [`str.split(regexp[, limit])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split) Starting with 1.6.0, these methods added as well-known symbol-based methods to be used transparently with ES6 string/regex machinery. ### `Buffer` support In order to support `Buffer` directly, most methods can accept buffers instead of strings. It speeds up all operations. Following signatures are supported: * `re2.exec(buf)` * `re2.test(buf)` * `re2.match(buf)` * `re2.search(buf)` * `re2.split(buf[, limit])` * `re2.replace(buf, replacer)` Differences with their string-based versions: * All buffers are assumed to be encoded as [UTF-8](http://en.wikipedia.org/wiki/UTF-8) (ASCII is a proper subset of UTF-8). * Instead of strings they return `Buffer` objects, even in composite objects. A buffer can be converted to a string with [`buf.toString()`](http://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end). * All offsets and lengths are in bytes, rather than characters (each UTF-8 character can occupy from 1 to 4 bytes). This way users can properly slice buffers without costly recalculations from characters to bytes. When `re2.replace()` is used with a replacer function, the replacer can return a buffer, or a string. But all arguments (except for an input object) will be strings, and an offset will be in characters. If you prefer to deal with buffers and byte offsets in a replacer function, set a property `useBuffers` to `true` on the function: ```js function strReplacer(match, offset, input) { // typeof match == "string" return "<= " + offset + " characters|"; } RE2("б").replace("абв", strReplacer); // "а<= 1 characters|в" function bufReplacer(match, offset, input) { // typeof match == "string" return "<= " + offset + " bytes|"; } bufReplacer.useBuffers = true; RE2("б").replace("абв", bufReplacer); // "а<= 2 bytes|в" ``` This feature works for string and buffer inputs. If a buffer was used as an input, its output will be returned as a buffer too, otherwise a string will be returned. ### Calculate length Two functions to calculate string sizes between [UTF-8](http://en.wikipedia.org/wiki/UTF-8) and [UTF-16](http://en.wikipedia.org/wiki/UTF-16) are exposed on `RE2`: * `RE2.getUtf8Length(str)` — calculates a buffer size in bytes to encode a UTF-16 string as a UTF-8 buffer. * `RE2.getUtf16Length(buf)` — calculates a string size in characters to encode a UTF-8 buffer as a UTF-16 string. JavaScript supports UCS-2 strings with 16-bit characters, while node.js 0.11 supports full UTF-16 as a default string. ### Property: `internalSource` Starting 1.8.0 property `source` emulates the same property of `RegExp`, meaning that it can be used to create an identical `RE2` or `RegExp` instance. Sometimes, for troubleshooting purposes, a user wants to inspect a `RE2` translated source. It is available as a read-only property called `internalSource`. ### Unicode warning level `RE2` engine always works in the Unicode mode. In most cases either there is no difference or the Unicode mode is actually preferred. But sometimes a user want a tight control over her regular expressions. For those cases, there is a static string property `RE2.unicodeWarningLevel`. Regular expressions in the Unicode mode work as usual. But if a regular expression lacks the Unicode flag, it is always added silently. ```js const x = /./; x.flags; // '' const y = new RE2(x); y.flags; // 'u' ``` In the latter case `RE2` can do following actions depending on `RE2.unicodeWarningLevel`: * `'nothing'` (the default): no warnings or notifications of any kind, a regular expression will be created with `'u'` flag. * `'warnOnce'`: warns exactly once the very first time, a regular expression will be created with `'u'` flag. * Assigning this value resets an internal flag, so `RE2` will warn once again. * `'warn'`: warns every time, a regular expression will be created with `'u'` flag. * `'throw'`: throws a `SyntaxError` every time. * All other warning level values are silently ignored on asignment leaving the previous value unchanged. Warnings and exceptions help to audit an application for stray non-Unicode regular expressions. ## How to install Installation: ``` npm install --save re2 ``` ## How to use It is used just like a `RegExp` object. ```js var RE2 = require("re2"); // with default flags var re = new RE2("a(b*)"); var result = re.exec("abbc"); console.log(result[0]); // "abb" console.log(result[1]); // "bb" result = re.exec("aBbC"); console.log(result[0]); // "a" console.log(result[1]); // "" // with explicit flags re = new RE2("a(b*)", "i"); result = re.exec("aBbC"); console.log(result[0]); // "aBb" console.log(result[1]); // "Bb" // from regular expression object var regexp = new RegExp("a(b*)", "i"); re = new RE2(regexp); result = re.exec("aBbC"); console.log(result[0]); // "aBb" console.log(result[1]); // "Bb" // from regular expression literal re = new RE2(/a(b*)/i); result = re.exec("aBbC"); console.log(result[0]); // "aBb" console.log(result[1]); // "Bb" // from another RE2 object var rex = new RE2(re); result = rex.exec("aBbC"); console.log(result[0]); // "aBb" console.log(result[1]); // "Bb" // shortcut result = new RE2("ab*").exec("abba"); // factory result = RE2("ab*").exec("abba"); ``` ## Limitations (Things RE2 does not support) `RE2` consciously avoids any regular expression features that require worst-case exponential time to evaluate. These features are essentially those that describe a Context-Free Language (CFL) rather than a Regular Expression, and are extensions to the traditional regular expression language because some people don't know when enough is enough. The most noteworthy missing features are backreferences and lookahead assertions. If your application uses these features, you should continue to use `RegExp`. But since these features are fundamentally vulnerable to [ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS), you should strongly consider replacing them. `RE2` will throw a `SyntaxError` if you try to declare a regular expression using these features. If you are evaluating an externally-provided regular expression, wrap your `RE2` declarations in a try-catch block. It allows to use `RegExp`, when `RE2` misses a feature: ```js var re = /(a)+(b)*/; try { re = new RE2(re); // use RE2 as a drop-in replacement } catch (e) { // suppress an error, and use // the original RegExp } var result = re.exec(sample); ``` In addition to these missing features, `RE2` also behaves somewhat differently from the built-in regular expression engine in corner cases. ### Backreferences `RE2` doesn't support backreferences, which are numbered references to previously matched groups, like so: `\1`, `\2`, and so on. Example of backrefrences: ```js /(cat|dog)\1/.test("catcat"); // true /(cat|dog)\1/.test("dogdog"); // true /(cat|dog)\1/.test("catdog"); // false /(cat|dog)\1/.test("dogcat"); // false ``` ### Lookahead assertions `RE2` doesn't support lookahead assertions, which are ways to allow a matching dependent on subsequent contents. ```js /abc(?=def)/; // match abc only if it is followed by def /abc(?!def)/; // match abc only if it is not followed by def ``` ### Mismatched behavior `RE2` and the built-in regex engines disagree a bit. Before you switch to `RE2`, verify that your regular expressions continue to work as expected. They should do so in the vast majority of cases. Here is an example of a case where they may not: ```js var RE2 = require("../re2"); var pattern = '(?:(a)|(b)|(c))+'; var built_in = new RegExp(pattern); var re2 = new RE2(pattern); var input = 'abc'; var bi_res = built_in.exec(input); var re2_res = re2.exec(input); console.log('bi_res: ' + bi_res); // prints: bi_res: abc,,,c console.log('re2_res : ' + re2_res); // prints: re2_res : abc,a,b,c ``` ### Unicode `RE2` always works in the Unicode mode. See `RE2.unicodeWarningLevel` above for more details on how to control warnings about this feature. ## Working on this project This project uses git submodules, so the correct way to get it is: git clone git@github.com:uhop/node-re2.git cd node-re2 git submodule update --init --recursive In order to build it, make sure that you have all necessary `gyp` dependencies for your platform, then run: npm install Or: yarn ## Release history - 1.10.5 *Bugfix for optional groups (thx [Josh Yudaken](https://github.com/qix)), the latest version of `re2`.* - 1.10.4 *Technical release: even better TypeScript types (thx [Louis Brann](https://github.com/louis-brann)).* - 1.10.3 *Technical release: missing reference to TS types (thx [Jamie Magee](https://github.com/JamieMagee)).* - 1.10.2 *Technical release: added TypeScript types (thx [Jamie Magee](https://github.com/JamieMagee)).* - 1.10.1 *Updated `re2` to the latest version (thx [Jamie Magee](https://github.com/JamieMagee)), dropped Node 6.* - 1.10.0 *Added back support for Node 6 and Node 8. Now Node 6-12 is supported.* - 1.9.0 *Refreshed dependencies to support Node 12. Only versions 10-12 are supported now (`v8` restrictions). For older versions use `node-re2@1.8`.* - 1.8.4 *Refreshed dependencies, removed `unistd.h` to compile on Windows.* - 1.8.3 *Refreshed dependencies, removed suppression of some warnings.* - 1.8.2 *Bugfix to support the null prototype for groups. Thx [Exter-N](https://github.com/Exter-N)!* - 1.8.1 *Bugfix for better source escaping.* - 1.8.0 *Clarified Unicode support, added `unicode` flag, added named groups — thx [Exter-N](https://github.com/Exter-N)! Bugfixes — thx [Barak Amar](https://github.com/nopcoder)!* - 1.7.0 *Implemented `sticky` and `flags` + bug fixes + more tests. Thx [Exter-N](https://github.com/Exter-N)!* - 1.6.2 *Bugfix for a prototype access. Thx [Exter-N](https://github.com/Exter-N)!* - 1.6.1 *Returned support for node 4 LTS. Thx [Kannan Goundan](https://github.com/cakoose)!* - 1.6.0 *Added well-known symbol-based methods of ES6. Refreshed NAN.* - 1.5.0 *Bugfixes, error checks, better docs. Thx [Jamie Davis](https://github.com/davisjam), and [omg](https://github.com/omg)!* - 1.4.1 *Minor corrections in README.* - 1.4.0 *Use re2 as a git submodule. Thx [Ben James](https://github.com/benhjames)!* - 1.3.3 *Refreshed dependencies.* - 1.3.2 *Updated references in README (re2 was moved to github).* - 1.3.1 *Refreshed dependencies, new Travis-CI config.* - 1.3.0 *Upgraded NAN to 1.6.3, now we support node.js 0.10.36, 0.12.0, and io.js 1.3.0. Thx @reid!* - 1.2.0 *Documented getUtfXLength() functions. Added support for `\c` and `\u` commands.* - 1.1.1 *Minor corrections in README.* - 1.1.0 *Buffer-based API is public. Unicode is fully supported.* - 1.0.0 *Implemented all `RegExp` methods, and all relevant `String` methods.* - 0.9.0 *The initial public release.* ## License BSD [npm-image]: https://img.shields.io/npm/v/re2.svg [npm-url]: https://npmjs.org/package/re2 [deps-image]: https://img.shields.io/david/uhop/node-re2.svg [deps-url]: https://david-dm.org/uhop/node-re2 [dev-deps-image]: https://img.shields.io/david/dev/uhop/node-re2.svg [dev-deps-url]: https://david-dm.org/uhop/node-re2?type=dev [travis-image]: https://img.shields.io/travis/uhop/node-re2.svg [travis-url]: https://travis-ci.org/uhop/node-re2 node-re2-1.10.5/binding.gyp000066400000000000000000000040501357256744100153610ustar00rootroot00000000000000{ "targets": [ { "target_name": "re2", "sources": [ "lib/addon.cc", "lib/new.cc", "lib/exec.cc", "lib/test.cc", "lib/match.cc", "lib/replace.cc", "lib/search.cc", "lib/split.cc", "lib/to_string.cc", "lib/accessors.cc", "lib/util.cc", "vendor/re2/bitstate.cc", "vendor/re2/compile.cc", "vendor/re2/dfa.cc", "vendor/re2/filtered_re2.cc", "vendor/re2/mimics_pcre.cc", "vendor/re2/nfa.cc", "vendor/re2/onepass.cc", "vendor/re2/parse.cc", "vendor/re2/perl_groups.cc", "vendor/re2/prefilter.cc", "vendor/re2/prefilter_tree.cc", "vendor/re2/prog.cc", "vendor/re2/re2.cc", "vendor/re2/regexp.cc", "vendor/re2/set.cc", "vendor/re2/simplify.cc", "vendor/re2/stringpiece.cc", "vendor/re2/tostring.cc", "vendor/re2/unicode_casefold.cc", "vendor/re2/unicode_groups.cc", "vendor/util/pcre.cc", "vendor/util/rune.cc", "vendor/util/strutil.cc" ], "cflags": [ "-std=c++11", "-Wall", "-Wextra", "-Wno-sign-compare", "-Wno-unused-parameter", "-Wno-missing-field-initializers", "-O3", "-g" ], "defines": [ "NDEBUG" ], "include_dirs": [ " #include #include NAN_GETTER(WrappedRE2::GetSource) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().Set(Nan::New("(?:)").ToLocalChecked()); return; } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(re2->source).ToLocalChecked()); } NAN_GETTER(WrappedRE2::GetInternalSource) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().Set(Nan::New("(?:)").ToLocalChecked()); return; } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(re2->regexp.pattern()).ToLocalChecked()); } NAN_GETTER(WrappedRE2::GetFlags) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().Set(Nan::New("").ToLocalChecked()); return; } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); std::string flags; if (re2->global) { flags = "g"; } if (re2->ignoreCase) { flags += "i"; } if (re2->multiline) { flags += "m"; } flags += "u"; if (re2->sticky) { flags += "y"; } info.GetReturnValue().Set(Nan::New(flags).ToLocalChecked()); } NAN_GETTER(WrappedRE2::GetGlobal) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().SetUndefined(); return; } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(re2->global); } NAN_GETTER(WrappedRE2::GetIgnoreCase) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().SetUndefined(); return; } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(re2->ignoreCase); } NAN_GETTER(WrappedRE2::GetMultiline) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().SetUndefined(); return; } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(re2->multiline); } NAN_GETTER(WrappedRE2::GetUnicode) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().SetUndefined(); return; } info.GetReturnValue().Set(true); } NAN_GETTER(WrappedRE2::GetSticky) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().SetUndefined(); return; } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(re2->sticky); } NAN_GETTER(WrappedRE2::GetLastIndex) { if (!WrappedRE2::HasInstance(info.This())) { info.GetReturnValue().SetUndefined(); return; } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(static_cast(re2->lastIndex)); } NAN_SETTER(WrappedRE2::SetLastIndex) { if (!WrappedRE2::HasInstance(info.This())) { return Nan::ThrowTypeError("Cannot set lastIndex of an invalid RE2 object."); } auto re2 = Nan::ObjectWrap::Unwrap(info.This()); if (value->IsNumber()) { int n = value->NumberValue(Nan::GetCurrentContext()).FromMaybe(0); re2->lastIndex = n <= 0 ? 0 : n; } } WrappedRE2::UnicodeWarningLevels WrappedRE2::unicodeWarningLevel; NAN_GETTER(WrappedRE2::GetUnicodeWarningLevel) { std::string level; switch (unicodeWarningLevel) { case THROW: level = "throw"; break; case WARN: level = "warn"; break; case WARN_ONCE: level = "warnOnce"; break; default: level = "nothing"; break; } info.GetReturnValue().Set(Nan::New(level).ToLocalChecked()); } NAN_SETTER(WrappedRE2::SetUnicodeWarningLevel) { if (value->IsString()) { auto size = Nan::DecodeBytes(value, Nan::UTF8); std::vector buffer(size + 1); auto data = &buffer[0]; Nan::DecodeWrite(data, size, value, Nan::UTF8); buffer[size] = '\0'; if (!strcmp(data, "throw")) { unicodeWarningLevel = THROW; return; } if (!strcmp(data, "warn")) { unicodeWarningLevel = WARN; return; } if (!strcmp(data, "warnOnce")) { unicodeWarningLevel = WARN_ONCE; alreadyWarnedAboutUnicode = false; return; } if (!strcmp(data, "nothing")) { unicodeWarningLevel = NOTHING; return; } } } node-re2-1.10.5/lib/addon.cc000066400000000000000000000051661357256744100154010ustar00rootroot00000000000000#include "./wrapped_re2.h" #include Nan::Persistent WrappedRE2::constructor; Nan::Persistent WrappedRE2::ctorTemplate; static NAN_METHOD(GetUtf8Length) { auto t = info[0]->ToString(Nan::GetCurrentContext()); if (t.IsEmpty()) { return; } info.GetReturnValue().Set(static_cast(Nan::DecodeBytes(t.ToLocalChecked(), Nan::UTF8))); } static NAN_METHOD(GetUtf16Length) { if (node::Buffer::HasInstance(info[0])) { const auto *s = node::Buffer::Data(info[0]); info.GetReturnValue().Set(static_cast(getUtf16Length(s, s + node::Buffer::Length(info[0])))); return; } info.GetReturnValue().Set(-1); } void WrappedRE2::Initialize(v8::Local exports, v8::Local module) { // prepare constructor template auto tpl = Nan::New(New); tpl->SetClassName(Nan::New("RE2").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); // prototype Nan::SetPrototypeMethod(tpl, "toString", ToString); Nan::SetPrototypeMethod(tpl, "exec", Exec); Nan::SetPrototypeMethod(tpl, "test", Test); Nan::SetPrototypeMethod(tpl, "match", Match); Nan::SetPrototypeMethod(tpl, "replace", Replace); Nan::SetPrototypeMethod(tpl, "search", Search); Nan::SetPrototypeMethod(tpl, "split", Split); auto proto = tpl->PrototypeTemplate(); Nan::SetAccessor(proto, Nan::New("source").ToLocalChecked(), GetSource); Nan::SetAccessor(proto, Nan::New("flags").ToLocalChecked(), GetFlags); Nan::SetAccessor(proto, Nan::New("global").ToLocalChecked(), GetGlobal); Nan::SetAccessor(proto, Nan::New("ignoreCase").ToLocalChecked(), GetIgnoreCase); Nan::SetAccessor(proto, Nan::New("multiline").ToLocalChecked(), GetMultiline); Nan::SetAccessor(proto, Nan::New("unicode").ToLocalChecked(), GetUnicode); Nan::SetAccessor(proto, Nan::New("sticky").ToLocalChecked(), GetSticky); Nan::SetAccessor(proto, Nan::New("lastIndex").ToLocalChecked(), GetLastIndex, SetLastIndex); Nan::SetAccessor(proto, Nan::New("internalSource").ToLocalChecked(), GetInternalSource); auto fun = Nan::GetFunction(tpl).ToLocalChecked(); Nan::Export(fun, "getUtf8Length", GetUtf8Length); Nan::Export(fun, "getUtf16Length", GetUtf16Length); Nan::SetAccessor(v8::Local(fun), Nan::New("unicodeWarningLevel").ToLocalChecked(), GetUnicodeWarningLevel, SetUnicodeWarningLevel); constructor.Reset(fun); ctorTemplate.Reset(tpl); // return constructor as module's export Nan::Set(module, Nan::New("exports").ToLocalChecked(), fun); } void Initialize(v8::Local exports, v8::Local module) { WrappedRE2::Initialize(exports, module); } NODE_MODULE(re2, Initialize) node-re2-1.10.5/lib/exec.cc000066400000000000000000000061061357256744100152330ustar00rootroot00000000000000#include "./wrapped_re2.h" #include "./util.h" #include #include NAN_METHOD(WrappedRE2::Exec) { // unpack arguments auto re2 = Nan::ObjectWrap::Unwrap(info.This()); if (!re2) { info.GetReturnValue().SetNull(); return; } StrVal str(info[0]); if (!str.data) { return; } size_t lastIndex = 0; if (str.isBuffer) { if ((re2->global || re2->sticky) && re2->lastIndex) { if (re2->lastIndex > str.size) { re2->lastIndex = 0; info.GetReturnValue().SetNull(); return; } lastIndex = re2->lastIndex; } } else { if ((re2->global || re2->sticky) && re2->lastIndex) { if (re2->lastIndex > str.length) { re2->lastIndex = 0; info.GetReturnValue().SetNull(); return; } for (size_t n = re2->lastIndex; n; --n) { lastIndex += getUtf8CharSize(str.data[lastIndex]); } } } // actual work std::vector groups(re2->regexp.NumberOfCapturingGroups() + 1); if (!re2->regexp.Match(str, lastIndex, str.size, re2->sticky ? re2::RE2::ANCHOR_START : re2::RE2::UNANCHORED, &groups[0], groups.size())) { if (re2->global || re2->sticky) { re2->lastIndex = 0; } info.GetReturnValue().SetNull(); return; } // form a result auto result = Nan::New(); int indexOffset = re2->global || re2->sticky ? re2->lastIndex : 0; if (str.isBuffer) { for (size_t i = 0, n = groups.size(); i < n; ++i) { const auto &item = groups[i]; if (item.data() != NULL) { Nan::Set(result, i, Nan::CopyBuffer(item.data(), item.size()).ToLocalChecked()); } else { Nan::Set(result, i, Nan::Undefined()); } } Nan::Set(result, Nan::New("index").ToLocalChecked(), Nan::New(indexOffset + static_cast(groups[0].data() - str.data))); } else { for (size_t i = 0, n = groups.size(); i < n; ++i) { const auto &item = groups[i]; if (item.data() != NULL) { Nan::Set(result, i, Nan::New(item.data(), item.size()).ToLocalChecked()); } else { Nan::Set(result, i, Nan::Undefined()); } } Nan::Set(result, Nan::New("index").ToLocalChecked(), Nan::New(indexOffset + static_cast(getUtf16Length(str.data + lastIndex, groups[0].data())))); } Nan::Set(result, Nan::New("input").ToLocalChecked(), info[0]); const auto &groupNames = re2->regexp.CapturingGroupNames(); if (!groupNames.empty()) { auto groups = Nan::New(); (void)groups->SetPrototype(Nan::GetCurrentContext(), Nan::Null()); for (auto group : groupNames) { auto value = Nan::Get(result, group.first); if (!value.IsEmpty()) { Nan::Set(groups, Nan::New(group.second).ToLocalChecked(), value.ToLocalChecked()); } } Nan::Set(result, Nan::New("groups").ToLocalChecked(), groups); } else { Nan::Set(result, Nan::New("groups").ToLocalChecked(), Nan::Undefined()); } if (re2->global || re2->sticky) { re2->lastIndex += str.isBuffer ? groups[0].data() - str.data + groups[0].size() - lastIndex : getUtf16Length(str.data + lastIndex, groups[0].data() + groups[0].size()); } info.GetReturnValue().Set(result); } node-re2-1.10.5/lib/match.cc000066400000000000000000000061241357256744100154030ustar00rootroot00000000000000#include "./wrapped_re2.h" #include "./util.h" #include NAN_METHOD(WrappedRE2::Match) { // unpack arguments auto re2 = Nan::ObjectWrap::Unwrap(info.This()); if (!re2) { info.GetReturnValue().SetNull(); return; } StrVal a(info[0]); if (!a.data) { return; } std::vector groups; re2::StringPiece str(a); size_t lastIndex = 0; auto anchor = re2::RE2::UNANCHORED; // actual work if (re2->global) { // global: collect all matches re2::StringPiece match; if (re2->sticky) { anchor = re2::RE2::ANCHOR_START; } while (re2->regexp.Match(str, lastIndex, a.size, anchor, &match, 1)) { groups.push_back(match); lastIndex = match.data() - a.data + match.size(); } if (groups.empty()) { info.GetReturnValue().SetNull(); return; } } else { // non-global: just like exec() if (re2->sticky) { for (size_t n = re2->lastIndex; n; --n) { lastIndex += getUtf8CharSize(a.data[lastIndex]); } anchor = RE2::ANCHOR_START; } groups.resize(re2->regexp.NumberOfCapturingGroups() + 1); if (!re2->regexp.Match(str, lastIndex, a.size, anchor, &groups[0], groups.size())) { if (re2->sticky) { re2->lastIndex = 0; } info.GetReturnValue().SetNull(); return; } } // form a result auto result = Nan::New(); if (a.isBuffer) { for (size_t i = 0, n = groups.size(); i < n; ++i) { const auto &item = groups[i]; if (item.data() != NULL) { Nan::Set(result, i, Nan::CopyBuffer(item.data(), item.size()).ToLocalChecked()); } } if (!re2->global) { Nan::Set(result, Nan::New("index").ToLocalChecked(), Nan::New(static_cast(groups[0].data() - a.data))); Nan::Set(result, Nan::New("input").ToLocalChecked(), info[0]); } } else { for (size_t i = 0, n = groups.size(); i < n; ++i) { const auto &item = groups[i]; if (item.data() != NULL) { Nan::Set(result, i, Nan::New(item.data(), item.size()).ToLocalChecked()); } } if (!re2->global) { Nan::Set(result, Nan::New("index").ToLocalChecked(), Nan::New(static_cast(getUtf16Length(a.data, groups[0].data())))); Nan::Set(result, Nan::New("input").ToLocalChecked(), info[0]); } } if (re2->global) { re2->lastIndex = 0; } else if (re2->sticky) { re2->lastIndex += a.isBuffer ? groups[0].data() - a.data + groups[0].size() - lastIndex : getUtf16Length(a.data + lastIndex, groups[0].data() + groups[0].size()); } if (!re2->global) { const auto &groupNames = re2->regexp.CapturingGroupNames(); if (!groupNames.empty()) { auto groups = Nan::New(); (void)groups->SetPrototype(Nan::GetCurrentContext(), Nan::Null()); for (auto group : groupNames) { auto value = Nan::Get(result, group.first); if (!value.IsEmpty()) { Nan::Set(groups, Nan::New(group.second).ToLocalChecked(), value.ToLocalChecked()); } } Nan::Set(result, Nan::New("groups").ToLocalChecked(), groups); } else { Nan::Set(result, Nan::New("groups").ToLocalChecked(), Nan::Undefined()); } } info.GetReturnValue().Set(result); } node-re2-1.10.5/lib/new.cc000066400000000000000000000176571357256744100151150ustar00rootroot00000000000000#include "./wrapped_re2.h" #include "./util.h" #include #include #include #include static char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; inline bool isUpperCaseAlpha(char ch) { return 'A' <= ch && ch <= 'Z'; } inline bool isHexadecimal(char ch) { return ('0' <= ch && ch <= '9') || ('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z'); } static bool translateRegExp(const char *data, size_t size, std::vector &buffer) { std::string result; bool changed = false; if (!size) { result = "(?:)"; changed = true; } for (size_t i = 0; i < size;) { char ch = data[i]; if (ch == '\\') { if (i + 1 < size) { ch = data[i + 1]; switch (ch) { case '\\': result += "\\\\"; i += 2; continue; case 'c': if (i + 2 < size) { ch = data[i + 2]; if (isUpperCaseAlpha(ch)) { result += "\\x"; result += hex[((ch - '@') / 16) & 15]; result += hex[(ch - '@') & 15]; i += 3; changed = true; continue; } } result += "\\c"; i += 2; continue; case 'u': if (i + 2 < size) { ch = data[i + 2]; if (isHexadecimal(ch)) { result += "\\x{"; result += ch; i += 3; for (size_t j = 0; j < 3 && i < size; ++i, ++j) { ch = data[i]; if (!isHexadecimal(ch)) { break; } result += ch; } result += '}'; changed = true; continue; } else if (ch == '{') { result += "\\x"; i += 2; changed = true; continue; } } result += "\\u"; i += 2; continue; default: result += "\\"; size_t sym_size = getUtf8CharSize(ch); result.append(data + i + 1, sym_size); i += sym_size + 1; continue; } } } else if (ch == '/') { result += "\\/"; i += 1; changed = true; continue; } else if (ch == '(' && i + 2 < size && data[i + 1] == '?' && data[i + 2] == '<') { if (i + 3 >= size || (data[i + 3] != '=' && data[i + 3] != '!')) { result += "(?P<"; i += 3; changed = true; continue; } } size_t sym_size = getUtf8CharSize(ch); result.append(data + i, sym_size); i += sym_size; } if (!changed) { return false; } buffer.resize(0); buffer.insert(buffer.end(), result.data(), result.data() + result.size()); buffer.push_back('\0'); return true; } static std::string escapeRegExp(const char *data, size_t size) { std::string result; if (!size) { result = "(?:)"; } size_t prevBackSlashes = 0; for (size_t i = 0; i < size;) { char ch = data[i]; if (ch == '\\') { ++prevBackSlashes; } else if (ch == '/' && !(prevBackSlashes & 1)) { result += "\\/"; i += 1; prevBackSlashes = 0; continue; } else { prevBackSlashes = 0; } size_t sym_size = getUtf8CharSize(ch); result.append(data + i, sym_size); i += sym_size; } return result; } bool WrappedRE2::alreadyWarnedAboutUnicode = false; static const char *depricationMessage = "BMP patterns aren't supported by node-re2. An implicit \"u\" flag is assumed by the RE2 constructor. In a future major version, calling the RE2 constructor without the \"u\" flag may become forbidden, or cause a different behavior. Please see https://github.com/uhop/node-re2/issues/21 for more information."; inline bool ensureUniqueNamedGroups(const std::map &groups) { std::unordered_set names; for (auto group : groups) { if (!names.insert(group.second).second) { return false; } } return true; } NAN_METHOD(WrappedRE2::New) { if (!info.IsConstructCall()) { // call a constructor and return the result std::vector> parameters(info.Length()); for (size_t i = 0, n = info.Length(); i < n; ++i) { parameters[i] = info[i]; } auto newObject = Nan::NewInstance(Nan::New(constructor), parameters.size(), ¶meters[0]); if (!newObject.IsEmpty()) { info.GetReturnValue().Set(newObject.ToLocalChecked()); } return; } // process arguments std::vector buffer; char *data = NULL; size_t size = 0; std::string source; bool global = false; bool ignoreCase = false; bool multiline = false; bool unicode = false; bool sticky = false; auto context = Nan::GetCurrentContext(); if (info.Length() > 1) { if (info[1]->IsString()) { size = Nan::DecodeBytes(info[1], Nan::UTF8); buffer.resize(size + 1); data = &buffer[0]; Nan::DecodeWrite(data, size, info[1], Nan::UTF8); buffer[size] = '\0'; } else if (node::Buffer::HasInstance(info[1])) { size = node::Buffer::Length(info[1]); data = node::Buffer::Data(info[1]); } for (size_t i = 0; i < size; ++i) { switch (data[i]) { case 'g': global = true; break; case 'i': ignoreCase = true; break; case 'm': multiline = true; break; case 'u': unicode = true; break; case 'y': sticky = true; break; } } size = 0; } bool needConversion = true; if (node::Buffer::HasInstance(info[0])) { size = node::Buffer::Length(info[0]); data = node::Buffer::Data(info[0]); source = escapeRegExp(data, size); } else if (info[0]->IsRegExp()) { const auto *re = v8::RegExp::Cast(*info[0]); auto t = re->GetSource(); size = Nan::DecodeBytes(t, Nan::UTF8); buffer.resize(size + 1); data = &buffer[0]; Nan::DecodeWrite(data, size, t, Nan::UTF8); buffer[size] = '\0'; source = escapeRegExp(data, size); v8::RegExp::Flags flags = re->GetFlags(); global = bool(flags & v8::RegExp::kGlobal); ignoreCase = bool(flags & v8::RegExp::kIgnoreCase); multiline = bool(flags & v8::RegExp::kMultiline); unicode = bool(flags & v8::RegExp::kUnicode); sticky = bool(flags & v8::RegExp::kSticky); } else if (info[0]->IsObject() && !info[0]->IsString()) { WrappedRE2 *re2 = nullptr; auto object = info[0]->ToObject(context).ToLocalChecked(); if (!object.IsEmpty() && object->InternalFieldCount() > 0) { re2 = Nan::ObjectWrap::Unwrap(object); } if (re2) { const auto &pattern = re2->regexp.pattern(); size = pattern.size(); buffer.resize(size); data = &buffer[0]; memcpy(data, pattern.data(), size); needConversion = false; source = re2->source; global = re2->global; ignoreCase = re2->ignoreCase; multiline = re2->multiline; unicode = true; sticky = re2->sticky; } } else if (info[0]->IsString()) { size = Nan::DecodeBytes(info[0], Nan::UTF8); buffer.resize(size + 1); data = &buffer[0]; Nan::DecodeWrite(data, size, info[0], Nan::UTF8); buffer[size] = '\0'; source = escapeRegExp(data, size); } if (!data) { return Nan::ThrowTypeError("Expected string, Buffer, RegExp, or RE2 as the 1st argument."); } if (!unicode) { switch (unicodeWarningLevel) { case THROW: return Nan::ThrowSyntaxError(depricationMessage); case WARN: printDeprecationWarning(depricationMessage); break; case WARN_ONCE: if (!alreadyWarnedAboutUnicode) { printDeprecationWarning(depricationMessage); alreadyWarnedAboutUnicode = true; } break; default: break; } } if (needConversion && translateRegExp(data, size, buffer)) { size = buffer.size() - 1; data = &buffer[0]; } // create and return an object re2::RE2::Options options; options.set_case_sensitive(!ignoreCase); options.set_one_line(!multiline); options.set_log_errors(false); // inappropriate when embedding std::unique_ptr re2(new WrappedRE2(re2::StringPiece(data, size), options, source, global, ignoreCase, multiline, sticky)); if (!re2->regexp.ok()) { return Nan::ThrowSyntaxError(re2->regexp.error().c_str()); } if (!ensureUniqueNamedGroups(re2->regexp.CapturingGroupNames())) { return Nan::ThrowSyntaxError("duplicate capture group name"); } re2->Wrap(info.This()); re2.release(); info.GetReturnValue().Set(info.This()); } node-re2-1.10.5/lib/replace.cc000066400000000000000000000265171357256744100157320ustar00rootroot00000000000000#include "./wrapped_re2.h" #include "./util.h" #include #include #include #include #include inline int getMaxSubmatch(const char *data, size_t size, const std::map &namedGroups) { int maxSubmatch = 0, index, index2; const char *nameBegin; const char *nameEnd; for (size_t i = 0; i < size;) { char ch = data[i]; if (ch == '$') { if (i + 1 < size) { ch = data[i + 1]; switch (ch) { case '$': case '&': case '`': case '\'': i += 2; continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': index = ch - '0'; if (i + 2 < size) { ch = data[i + 2]; if ('0' <= ch && ch <= '9') { index2 = index * 10 + (ch - '0'); if (maxSubmatch < index2) maxSubmatch = index2; i += 3; continue; } } if (maxSubmatch < index) maxSubmatch = index; i += 2; continue; case '<': nameBegin = data + i + 2; nameEnd = (const char *)memchr(nameBegin, '>', size - i - 2); if (nameEnd) { std::string name(nameBegin, nameEnd - nameBegin); auto group = namedGroups.find(name); if (group != namedGroups.end()) { index = group->second; if (maxSubmatch < index) maxSubmatch = index; } i = nameEnd + 1 - data; } else { i += 2; } continue; } } ++i; continue; } i += getUtf8CharSize(ch); } return maxSubmatch; } inline std::string replace(const char *data, size_t size, const std::vector &groups, const re2::StringPiece &str, const std::map &namedGroups) { std::string result; size_t index, index2; const char *nameBegin; const char *nameEnd; for (size_t i = 0; i < size;) { char ch = data[i]; if (ch == '$') { if (i + 1 < size) { ch = data[i + 1]; switch (ch) { case '$': result += ch; i += 2; continue; case '&': result += groups[0].as_string(); i += 2; continue; case '`': result += std::string(str.data(), groups[0].data() - str.data()); i += 2; continue; case '\'': result += std::string(groups[0].data() + groups[0].size(), str.data() + str.size() - groups[0].data() - groups[0].size()); i += 2; continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': index = ch - '0'; if (i + 2 < size) { ch = data[i + 2]; if ('0' <= ch && ch <= '9') { i += 3; index2 = index * 10 + (ch - '0'); if (index2 && index2 < groups.size()) { result += groups[index2].as_string(); continue; } result += '$'; result += '0' + index; result += ch; continue; } ch = '0' + index; } i += 2; if (index && index < groups.size()) { result += groups[index].as_string(); continue; } result += '$'; result += ch; continue; case '<': if (!namedGroups.empty()) { nameBegin = data + i + 2; nameEnd = (const char *)memchr(nameBegin, '>', size - i - 2); if (nameEnd) { std::string name(nameBegin, nameEnd - nameBegin); auto group = namedGroups.find(name); if (group != namedGroups.end()) { index = group->second; result += groups[index].as_string(); } i = nameEnd + 1 - data; } else { result += "$<"; i += 2; } } else { result += "$<"; i += 2; } continue; } } result += '$'; ++i; continue; } size_t sym_size = getUtf8CharSize(ch); result.append(data + i, sym_size); i += sym_size; } return result; } static Nan::Maybe replace(WrappedRE2 *re2, const StrVal &replacee, const char *replacer, size_t replacer_size) { const re2::StringPiece str = replacee; const char *data = str.data(); size_t size = str.size(); const auto &namedGroups = re2->regexp.NamedCapturingGroups(); std::vector groups(std::min(re2->regexp.NumberOfCapturingGroups(), getMaxSubmatch(replacer, replacer_size, namedGroups)) + 1); const auto &match = groups[0]; size_t lastIndex = 0; std::string result; auto anchor = re2::RE2::UNANCHORED; if (re2->sticky) { if (!re2->global) { if (replacee.isBuffer) { lastIndex = re2->lastIndex; } else { for (size_t n = re2->lastIndex; n; --n) { lastIndex += getUtf8CharSize(data[lastIndex]); } } } anchor = re2::RE2::ANCHOR_START; } if (lastIndex) { result = std::string(data, lastIndex); } bool noMatch = true; while (lastIndex <= size && re2->regexp.Match(str, lastIndex, size, anchor, &groups[0], groups.size())) { noMatch = false; if (!re2->global && re2->sticky) { re2->lastIndex += replacee.isBuffer ? match.data() - data + match.size() - lastIndex : getUtf16Length(data + lastIndex, match.data() + match.size()); } if (match.size()) { if (match.data() == data || match.data() - data > lastIndex) { result += std::string(data + lastIndex, match.data() - data - lastIndex); } result += replace(replacer, replacer_size, groups, str, namedGroups); lastIndex = match.data() - data + match.size(); } else { result += replace(replacer, replacer_size, groups, str, namedGroups); size_t sym_size = getUtf8CharSize(data[lastIndex]); if (lastIndex < size) { result.append(data + lastIndex, sym_size); } lastIndex += sym_size; } if (!re2->global) { break; } } if (lastIndex < size) { result += std::string(data + lastIndex, size - lastIndex); } if (re2->global) { re2->lastIndex = 0; } else if (re2->sticky) { if (noMatch) { re2->lastIndex = 0; } } return Nan::Just(result); } inline Nan::Maybe replace(const Nan::Callback *replacer, const std::vector &groups, const re2::StringPiece &str, const v8::Local &input, bool useBuffers, const std::map &namedGroups) { std::vector> argv; auto context = Nan::GetCurrentContext(); if (useBuffers) { for (size_t i = 0, n = groups.size(); i < n; ++i) { const auto &item = groups[i]; argv.push_back(Nan::CopyBuffer(item.data(), item.size()).ToLocalChecked()); } argv.push_back(Nan::New(static_cast(groups[0].data() - str.data()))); } else { for (size_t i = 0, n = groups.size(); i < n; ++i) { const auto &item = groups[i]; argv.push_back(Nan::New(item.data(), item.size()).ToLocalChecked()); } argv.push_back(Nan::New(static_cast(getUtf16Length(str.data(), groups[0].data())))); } argv.push_back(input); if (!namedGroups.empty()) { auto groups = Nan::New(); (void)groups->SetPrototype(context, Nan::Null()); for (std::pair group : namedGroups) { Nan::Set(groups, Nan::New(group.first).ToLocalChecked(), argv[group.second]); } argv.push_back(groups); } auto maybeResult = Nan::CallAsFunction(replacer->GetFunction(), context->Global(), static_cast(argv.size()), &argv[0]); if (maybeResult.IsEmpty()) { return Nan::Nothing(); } auto result = maybeResult.ToLocalChecked(); if (node::Buffer::HasInstance(result)) { return Nan::Just(std::string(node::Buffer::Data(result), node::Buffer::Length(result))); } StrVal val = result; return Nan::Just(std::string(val.data, val.size)); } static Nan::Maybe replace(WrappedRE2 *re2, const StrVal &replacee, const Nan::Callback *replacer, const v8::Local &input, bool useBuffers) { const re2::StringPiece str = replacee; const char *data = str.data(); size_t size = str.size(); std::vector groups(re2->regexp.NumberOfCapturingGroups() + 1); const auto &match = groups[0]; size_t lastIndex = 0; std::string result; auto anchor = re2::RE2::UNANCHORED; if (re2->sticky) { if (!re2->global) { if (replacee.isBuffer) { lastIndex = re2->lastIndex; } else { for (size_t n = re2->lastIndex; n; --n) { lastIndex += getUtf8CharSize(data[lastIndex]); } } } anchor = RE2::ANCHOR_START; } if (lastIndex) { result = std::string(data, lastIndex); } const auto &namedGroups = re2->regexp.NamedCapturingGroups(); bool noMatch = true; while (lastIndex <= size && re2->regexp.Match(str, lastIndex, size, anchor, &groups[0], groups.size())) { noMatch = false; if (!re2->global && re2->sticky) { re2->lastIndex += replacee.isBuffer ? match.data() - data + match.size() - lastIndex : getUtf16Length(data + lastIndex, match.data() + match.size()); } if (match.size()) { if (match.data() == data || match.data() - data > lastIndex) { result += std::string(data + lastIndex, match.data() - data - lastIndex); } const auto part = replace(replacer, groups, str, input, useBuffers, namedGroups); if (part.IsNothing()) { return part; } result += part.FromJust(); lastIndex = match.data() - data + match.size(); } else { const auto part = replace(replacer, groups, str, input, useBuffers, namedGroups); if (part.IsNothing()) { return part; } result += part.FromJust(); size_t sym_size = getUtf8CharSize(data[lastIndex]); if (lastIndex < size) { result.append(data + lastIndex, sym_size); } lastIndex += sym_size; } if (!re2->global) { break; } } if (lastIndex < size) { result += std::string(data + lastIndex, size - lastIndex); } if (re2->global) { re2->lastIndex = 0; } else if (re2->sticky) { if (noMatch) { re2->lastIndex = 0; } } return Nan::Just(result); } static bool requiresBuffers(const v8::Local &f) { auto flag(Nan::Get(f, Nan::New("useBuffers").ToLocalChecked()).ToLocalChecked()); if (flag->IsUndefined() || flag->IsNull() || flag->IsFalse()) { return false; } if (flag->IsNumber()) { return flag->NumberValue(Nan::GetCurrentContext()).FromMaybe(0) != 0; } if (flag->IsString()) { return flag->ToString(Nan::GetCurrentContext()).ToLocalChecked()->Length() > 0; } return true; } NAN_METHOD(WrappedRE2::Replace) { auto re2 = Nan::ObjectWrap::Unwrap(info.This()); if (!re2) { info.GetReturnValue().Set(info[0]); return; } StrVal replacee = info[0]; if (!replacee.data) { info.GetReturnValue().Set(info[0]); return; } std::string result; if (info[1]->IsFunction()) { auto fun = info[1].As(); const std::unique_ptr cb(new Nan::Callback(fun)); const auto replaced = replace(re2, replacee, cb.get(), info[0], requiresBuffers(fun)); if (replaced.IsNothing()) { info.GetReturnValue().Set(info[0]); return; } result = replaced.FromJust(); } else { StrVal replacer = info[1]; if (!replacer.data) { info.GetReturnValue().Set(info[0]); return; } const auto replaced = replace(re2, replacee, replacer.data, replacer.size); if (replaced.IsNothing()) { info.GetReturnValue().Set(info[0]); return; } result = replaced.FromJust(); } if (replacee.isBuffer) { info.GetReturnValue().Set(Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked()); return; } info.GetReturnValue().Set(Nan::New(result).ToLocalChecked()); } node-re2-1.10.5/lib/search.cc000066400000000000000000000011351357256744100155510ustar00rootroot00000000000000#include "./wrapped_re2.h" #include "./util.h" NAN_METHOD(WrappedRE2::Search) { // unpack arguments auto re2 = Nan::ObjectWrap::Unwrap(info.This()); if (!re2) { info.GetReturnValue().Set(-1); return; } StrVal a = info[0]; if (!a.data) { return; } // actual work re2::StringPiece match; if (re2->regexp.Match(a, 0, a.size, re2->sticky ? re2::RE2::ANCHOR_START : re2::RE2::UNANCHORED, &match, 1)) { info.GetReturnValue().Set(static_cast(a.isBuffer ? match.data() - a.data : getUtf16Length(a.data, match.data()))); return; } info.GetReturnValue().Set(-1); } node-re2-1.10.5/lib/split.cc000066400000000000000000000041611357256744100154410ustar00rootroot00000000000000#include "./wrapped_re2.h" #include "./util.h" #include #include #include NAN_METHOD(WrappedRE2::Split) { auto result = Nan::New(); // unpack arguments auto re2 = Nan::ObjectWrap::Unwrap(info.This()); if (!re2) { Nan::Set(result, 0, info[0]); info.GetReturnValue().Set(result); return; } StrVal a = info[0]; if (!a.data) { return; } re2::StringPiece str = a; size_t limit = std::numeric_limits::max(); if (info.Length() > 1 && info[1]->IsNumber()) { size_t lim = info[1]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0); if (lim > 0) { limit = lim; } } // actual work std::vector groups(re2->regexp.NumberOfCapturingGroups() + 1), pieces; const auto &match = groups[0]; size_t lastIndex = 0; while (lastIndex < a.size && re2->regexp.Match(str, lastIndex, a.size, RE2::UNANCHORED, &groups[0], groups.size())) { if (match.size()) { pieces.push_back(re2::StringPiece(a.data + lastIndex, match.data() - a.data - lastIndex)); lastIndex = match.data() - a.data + match.size(); pieces.insert(pieces.end(), groups.begin() + 1, groups.end()); } else { size_t sym_size = getUtf8CharSize(a.data[lastIndex]); pieces.push_back(re2::StringPiece(a.data + lastIndex, sym_size)); lastIndex += sym_size; } if (pieces.size() >= limit) { break; } } if (pieces.size() < limit && (lastIndex < a.size || (lastIndex == a.size && match.size()))) { pieces.push_back(re2::StringPiece(a.data + lastIndex, a.size - lastIndex)); } if (pieces.empty()) { Nan::Set(result, 0, info[0]); info.GetReturnValue().Set(result); return; } // form a result if (a.isBuffer) { for (size_t i = 0, n = std::min(pieces.size(), limit); i < n; ++i) { const auto &item = pieces[i]; Nan::Set(result, i, Nan::CopyBuffer(item.data(), item.size()).ToLocalChecked()); } } else { for (size_t i = 0, n = std::min(pieces.size(), limit); i < n; ++i) { const auto &item = pieces[i]; Nan::Set(result, i, Nan::New(item.data(), item.size()).ToLocalChecked()); } } info.GetReturnValue().Set(result); } node-re2-1.10.5/lib/test.cc000066400000000000000000000027131357256744100152660ustar00rootroot00000000000000#include "./wrapped_re2.h" #include "./util.h" #include #include NAN_METHOD(WrappedRE2::Test) { // unpack arguments auto re2 = Nan::ObjectWrap::Unwrap(info.This()); if (!re2) { info.GetReturnValue().Set(false); return; } StrVal str = info[0]; if (!str.data) { return; } size_t lastIndex = 0; if (str.isBuffer) { if ((re2->global || re2->sticky) && re2->lastIndex) { if (re2->lastIndex > str.size) { re2->lastIndex = 0; info.GetReturnValue().Set(false); return; } lastIndex = re2->lastIndex; } } else { if ((re2->global || re2->sticky) && re2->lastIndex) { if (re2->lastIndex > str.length) { re2->lastIndex = 0; info.GetReturnValue().Set(false); return; } for (size_t n = re2->lastIndex; n; --n) { lastIndex += getUtf8CharSize(str.data[lastIndex]); } } } // actual work if (re2->global || re2->sticky) { re2::StringPiece match; if (re2->regexp.Match(str, lastIndex, str.size, re2->sticky ? re2::RE2::ANCHOR_START : re2::RE2::UNANCHORED, &match, 1)) { re2->lastIndex += str.isBuffer ? match.data() - str.data + match.size() - lastIndex : getUtf16Length(str.data + lastIndex, match.data() + match.size()); info.GetReturnValue().Set(true); return; } re2->lastIndex = 0; info.GetReturnValue().Set(false); return; } info.GetReturnValue().Set(re2->regexp.Match(str, lastIndex, str.size, re2::RE2::UNANCHORED, NULL, 0)); } node-re2-1.10.5/lib/to_string.cc000066400000000000000000000011101357256744100163050ustar00rootroot00000000000000#include "./wrapped_re2.h" #include NAN_METHOD(WrappedRE2::ToString) { // unpack arguments auto re2 = Nan::ObjectWrap::Unwrap(info.This()); if (!re2) { info.GetReturnValue().SetEmptyString(); return; } // actual work std::string buffer("/"); buffer += re2->regexp.pattern(); buffer += "/"; if (re2->global) { buffer += "g"; } if (re2->ignoreCase) { buffer += "i"; } if (re2->multiline) { buffer += "m"; } buffer += "u"; if (re2->sticky) { buffer += "y"; } info.GetReturnValue().Set(Nan::New(buffer).ToLocalChecked()); } node-re2-1.10.5/lib/util.cc000066400000000000000000000050221357256744100152600ustar00rootroot00000000000000#include "./util.h" #include #include #include StrVal::StrVal(const v8::Local &arg) : data(NULL), size(0), isBuffer(false) { if (node::Buffer::HasInstance(arg)) { isBuffer = true; size = length = node::Buffer::Length(arg); data = node::Buffer::Data(arg); } else { auto t = arg->ToString(Nan::GetCurrentContext()); if (!t.IsEmpty()) { auto s = t.ToLocalChecked(); length = Nan::DecodeBytes(s); size = Nan::DecodeBytes(s, Nan::UTF8); buffer.resize(size + 1); data = &buffer[0]; Nan::DecodeWrite(data, size, s, Nan::UTF8); buffer[size] = '\0'; } } } void consoleCall(const v8::Local &methodName, v8::Local text) { auto context = Nan::GetCurrentContext(); auto maybeConsole = bind( Nan::Get(context->Global(), Nan::New("console").ToLocalChecked()), [context](v8::Local console) { return console->ToObject(context); }); if (maybeConsole.IsEmpty()) return; auto console = maybeConsole.ToLocalChecked(); auto maybeMethod = bind( Nan::Get(console, methodName), [context](v8::Local method) { return method->ToObject(context); }); if (maybeMethod.IsEmpty()) return; auto method = maybeMethod.ToLocalChecked(); if (!method->IsFunction()) return; Nan::CallAsFunction(method, console, 1, &text); } void printDeprecationWarning(const char *warning) { std::string prefixedWarning = "DeprecationWarning: "; prefixedWarning += warning; consoleCall(Nan::New("error").ToLocalChecked(), Nan::New(prefixedWarning).ToLocalChecked()); } v8::Local callToString(const v8::Local &object) { auto context = Nan::GetCurrentContext(); auto maybeMethod = bind( Nan::Get(object, Nan::New("toString").ToLocalChecked()), [context](v8::Local method) { return method->ToObject(context); }); if (maybeMethod.IsEmpty()) return Nan::New("No toString() is found").ToLocalChecked(); auto method = maybeMethod.ToLocalChecked(); if (!method->IsFunction()) return Nan::New("No toString() is found").ToLocalChecked(); auto maybeResult = Nan::CallAsFunction(method, object, 0, nullptr); if (maybeResult.IsEmpty()) { return Nan::New("nothing was returned").ToLocalChecked(); } auto result = maybeResult.ToLocalChecked(); if (result->IsObject()) { return callToString(result->ToObject(context).ToLocalChecked()); } Nan::Utf8String val(result->ToString(context).ToLocalChecked()); return Nan::New(std::string(*val, val.length())).ToLocalChecked(); } node-re2-1.10.5/lib/util.h000066400000000000000000000014101357256744100151170ustar00rootroot00000000000000#ifndef UTIL_H_ #define UTIL_H_ #include "./wrapped_re2.h" #include struct StrVal { std::vector buffer; char *data; size_t size, length; bool isBuffer; StrVal() : data(NULL), size(0), length(0), isBuffer(false) {} StrVal(const v8::Local &arg); operator re2::StringPiece() const { return re2::StringPiece(data, size); } }; template inline v8::MaybeLocal bind(v8::MaybeLocal

param, L lambda) { return param.IsEmpty() ? v8::MaybeLocal() : lambda(param.ToLocalChecked()); } void consoleCall(const v8::Local &methodName, v8::Local text); void printDeprecationWarning(const char *warning); v8::Local callToString(const v8::Local &object); #endif node-re2-1.10.5/lib/wrapped_re2.h000066400000000000000000000054321357256744100163640ustar00rootroot00000000000000#ifndef WRAPPED_RE2_H_ #define WRAPPED_RE2_H_ #include #include #include #include class WrappedRE2 : public Nan::ObjectWrap { private: WrappedRE2(const re2::StringPiece &pattern, const re2::RE2::Options &options, const std::string &s, const bool &g, const bool &i, const bool &m, const bool &y) : regexp(pattern, options), source(s), global(g), ignoreCase(i), multiline(m), sticky(y), lastIndex(0) {} static NAN_METHOD(New); static NAN_METHOD(ToString); static NAN_GETTER(GetSource); static NAN_GETTER(GetFlags); static NAN_GETTER(GetGlobal); static NAN_GETTER(GetIgnoreCase); static NAN_GETTER(GetMultiline); static NAN_GETTER(GetUnicode); static NAN_GETTER(GetSticky); static NAN_GETTER(GetLastIndex); static NAN_SETTER(SetLastIndex); static NAN_GETTER(GetInternalSource); // RegExp methods static NAN_METHOD(Exec); static NAN_METHOD(Test); // String methods static NAN_METHOD(Match); static NAN_METHOD(Replace); static NAN_METHOD(Search); static NAN_METHOD(Split); // strict Unicode warning support static NAN_GETTER(GetUnicodeWarningLevel); static NAN_SETTER(SetUnicodeWarningLevel); static Nan::Persistent constructor; static Nan::Persistent ctorTemplate; public: static void Initialize(v8::Local exports, v8::Local module); static inline bool HasInstance(v8::Local object) { return Nan::New(ctorTemplate)->HasInstance(object); } enum UnicodeWarningLevels { NOTHING, WARN_ONCE, WARN, THROW }; static UnicodeWarningLevels unicodeWarningLevel; static bool alreadyWarnedAboutUnicode; re2::RE2 regexp; std::string source; bool global; bool ignoreCase; bool multiline; bool sticky; size_t lastIndex; }; // utilities inline size_t getUtf8Length(const uint16_t *from, const uint16_t *to) { size_t n = 0; while (from != to) { uint16_t ch = *from++; if (ch <= 0x7F) ++n; else if (ch <= 0x7FF) n += 2; else if (0xD800 <= ch && ch <= 0xDFFF) { n += 4; if (from == to) break; ++from; } else if (ch < 0xFFFF) n += 3; else n += 4; } return n; } inline size_t getUtf16Length(const char *from, const char *to) { size_t n = 0; while (from != to) { unsigned ch = *from & 0xFF; if (ch < 0xF0) { if (ch < 0x80) { ++from; } else { if (ch < 0xE0) { from += 2; if (from == to + 1) { ++n; break; } } else { from += 3; if (from > to && from < to + 3) { ++n; break; } } } ++n; } else { from += 4; n += 2; if (from > to && from < to + 4) break; } } return n; } inline size_t getUtf8CharSize(char ch) { return ((0xE5000000 >> ((ch >> 3) & 0x1E)) & 3) + 1; } #endif node-re2-1.10.5/package-lock.json000066400000000000000000000022251357256744100164440ustar00rootroot00000000000000{ "name": "re2", "version": "1.10.5", "lockfileVersion": 1, "requires": true, "dependencies": { "heya-ice": { "version": "0.1.11", "resolved": "https://registry.npmjs.org/heya-ice/-/heya-ice-0.1.11.tgz", "integrity": "sha1-XW2lnGC1nHAjqDRw+26XcddwWEk=", "dev": true }, "heya-unify": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/heya-unify/-/heya-unify-0.2.7.tgz", "integrity": "sha512-d/4NacYl52tt4ofbP7gz+YmbjLrI2jkrRxSSd1a26yXfRS1vQxmZkZ6L+O1xUsgDSwx4HCDWR5U+ZFykdoHVig==", "dev": true, "requires": { "heya-ice": "^0.1.11" } }, "heya-unit": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/heya-unit/-/heya-unit-0.3.0.tgz", "integrity": "sha1-eXR4IIyBnUxbf+NWrEwbhO67ubc=", "dev": true, "requires": { "heya-ice": ">=0.1", "heya-unify": ">=0.2" } }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" } } } node-re2-1.10.5/package.json000066400000000000000000000015001357256744100155110ustar00rootroot00000000000000{ "name": "re2", "version": "1.10.5", "description": "Bindings for RE2: fast, safe alternative to backtracking regular expression engines.", "homepage": "http://github.com/uhop/node-re2", "bugs": "http://github.com/uhop/node-re2/issues", "main": "re2.js", "types": "re2.d.ts", "directories": { "test": "tests" }, "dependencies": { "nan": "^2.14.0" }, "devDependencies": { "heya-unit": "^0.3.0" }, "scripts": { "test": "node tests/tests.js" }, "github": "http://github.com/uhop/node-re2", "repository": { "type": "git", "url": "git://github.com/uhop/node-re2.git" }, "keywords": [ "RegExp", "RegEx", "text processing", "PCRE alternative" ], "author": "Eugene Lazutkin (http://lazutkin.com/)", "license": "BSD-3-Clause" } node-re2-1.10.5/re2.d.ts000066400000000000000000000001101357256744100145010ustar00rootroot00000000000000declare module 're2' { class RE2 extends RegExp {} export = RE2; } node-re2-1.10.5/re2.js000066400000000000000000000011131357256744100142510ustar00rootroot00000000000000'use strict'; var RE2 = require('./build/Release/re2.node'); if (typeof Symbol != 'undefined') { Symbol.match && (RE2.prototype[Symbol.match] = function(str) { return this.match(str); }); Symbol.search && (RE2.prototype[Symbol.search] = function(str) { return this.search(str); }); Symbol.replace && (RE2.prototype[Symbol.replace] = function(str, repl) { return this.replace(str, repl); }); Symbol.split && (RE2.prototype[Symbol.split] = function(str, limit) { return this.split(str, limit); }); } module.exports = RE2; node-re2-1.10.5/tests/000077500000000000000000000000001357256744100143715ustar00rootroot00000000000000node-re2-1.10.5/tests/test_exec.js000066400000000000000000000171611357256744100167200ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ // These tests are copied from MDN: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec function test_execBasic(t) { "use strict"; var re = new RE2("quick\\s(brown).+?(jumps)", "ig"); eval(t.TEST("re.source === 'quick\\\\s(brown).+?(jumps)'")); eval(t.TEST("re.ignoreCase")); eval(t.TEST("re.global")); eval(t.TEST("!re.multiline")); var result = re.exec("The Quick Brown Fox Jumps Over The Lazy Dog"); eval(t.TEST("t.unify(result, ['Quick Brown Fox Jumps', 'Brown', 'Jumps'])")); eval(t.TEST("result.index === 4")); eval(t.TEST("result.input === 'The Quick Brown Fox Jumps Over The Lazy Dog'")); eval(t.TEST("re.lastIndex === 25")); }, function test_execSucc(t) { "use strict"; var str = "abbcdefabh"; var re = new RE2("ab*", "g"); var result = re.exec(str); eval(t.TEST("!!result")); eval(t.TEST("result[0] === 'abb'")); eval(t.TEST("result.index === 0")); eval(t.TEST("re.lastIndex === 3")); result = re.exec(str); eval(t.TEST("!!result")); eval(t.TEST("result[0] === 'ab'")); eval(t.TEST("result.index === 7")); eval(t.TEST("re.lastIndex === 9")); result = re.exec(str); eval(t.TEST("!result")); }, function test_execSimple(t) { "use strict"; var re = new RE2("(hello \\S+)"); var result = re.exec("This is a hello world!"); eval(t.TEST("result[1] === 'hello world!'")); }, function test_execFail(t) { "use strict"; var re = new RE2("(a+)?(b+)?"); var result = re.exec("aaabb"); eval(t.TEST("result[1] === 'aaa'")); eval(t.TEST("result[2] === 'bb'")); result = re.exec("aaacbb"); eval(t.TEST("result[1] === 'aaa'")); eval(t.TEST("result[2] === undefined")); eval(t.TEST("result.length === 3")); }, function test_execAnchoredToBeginning(t) { "use strict"; var re = RE2('^hello', 'g'); var result = re.exec("hellohello"); eval(t.TEST("t.unify(result, ['hello'])")); eval(t.TEST("result.index === 0")); eval(t.TEST("re.lastIndex === 5")); eval(t.TEST("re.exec('hellohello') === null")); }, function test_execInvalid(t) { "use strict"; var re = RE2(''); try { re.exec({ toString() { throw "corner"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner'")); } }, function test_execAnchor1(t) { "use strict"; var re = new RE2("b|^a", "g"); var result = re.exec("aabc"); eval(t.TEST("!!result")); eval(t.TEST("result.index === 0")); eval(t.TEST("re.lastIndex === 1")); result = re.exec("aabc"); eval(t.TEST("!!result")); eval(t.TEST("result.index === 2")); eval(t.TEST("re.lastIndex === 3")); result = re.exec("aabc"); eval(t.TEST("!result")); }, function test_execAnchor2(t) { "use strict"; var re = new RE2("(?:^a)", "g"); var result = re.exec("aabc"); eval(t.TEST("!!result")); eval(t.TEST("result.index === 0")); eval(t.TEST("re.lastIndex === 1")); result = re.exec("aabc"); eval(t.TEST("!result")); }, // Unicode tests function test_execUnicode(t) { "use strict"; var re = new RE2("охотник\\s(желает).+?(где)", "ig"); eval(t.TEST("re.source === 'охотник\\\\s(желает).+?(где)'")); eval(t.TEST("re.ignoreCase")); eval(t.TEST("re.global")); eval(t.TEST("!re.multiline")); var result = re.exec("Каждый Охотник Желает Знать Где Сидит Фазан"); eval(t.TEST("t.unify(result, ['Охотник Желает Знать Где', 'Желает', 'Где'])")); eval(t.TEST("result.index === 7")); eval(t.TEST("result.input === 'Каждый Охотник Желает Знать Где Сидит Фазан'")); eval(t.TEST("re.lastIndex === 31")); eval(t.TEST("result.input.substr(result.index) === 'Охотник Желает Знать Где Сидит Фазан'")); eval(t.TEST("result.input.substr(re.lastIndex) === ' Сидит Фазан'")); }, function test_execUnicodeSubsequent(t) { "use strict"; var str = "аббвгдеабё"; var re = new RE2("аб*", "g"); var result = re.exec(str); eval(t.TEST("!!result")); eval(t.TEST("result[0] === 'абб'")); eval(t.TEST("result.index === 0")); eval(t.TEST("re.lastIndex === 3")); result = re.exec(str); eval(t.TEST("!!result")); eval(t.TEST("result[0] === 'аб'")); eval(t.TEST("result.index === 7")); eval(t.TEST("re.lastIndex === 9")); result = re.exec(str); eval(t.TEST("!result")); }, function test_execUnicodeSupplementary(t) { "use strict"; var re = new RE2("\\u{1F603}", "g"); eval(t.TEST("re.source === '\\\\u{1F603}'")); eval(t.TEST("re.internalSource === '\\\\x{1F603}'")); eval(t.TEST("!re.ignoreCase")); eval(t.TEST("re.global")); eval(t.TEST("!re.multiline")); var result = re.exec("\u{1F603}"); // 1F603 is the SMILING FACE WITH OPEN MOUTH emoji eval(t.TEST("t.unify(result, ['\\u{1F603}'])")); eval(t.TEST("result.index === 0")); eval(t.TEST("result.input === '\\u{1F603}'")); eval(t.TEST("re.lastIndex === 2")); var re2 = new RE2(".", "g"); eval(t.TEST("re2.source === '.'")); eval(t.TEST("!re2.ignoreCase")); eval(t.TEST("re2.global")); eval(t.TEST("!re2.multiline")); var result2 = re2.exec("\u{1F603}"); eval(t.TEST("t.unify(result2, ['\\u{1F603}'])")); eval(t.TEST("result2.index === 0")); eval(t.TEST("result2.input === '\\u{1F603}'")); eval(t.TEST("re2.lastIndex === 2")); var re3 = new RE2("[\u{1F603}-\u{1F605}]", "g"); eval(t.TEST("re3.source === '[\u{1F603}-\u{1F605}]'")); eval(t.TEST("!re3.ignoreCase")); eval(t.TEST("re3.global")); eval(t.TEST("!re3.multiline")); var result3 = re3.exec("\u{1F604}"); eval(t.TEST("t.unify(result3, ['\\u{1F604}'])")); eval(t.TEST("result3.index === 0")); eval(t.TEST("result3.input === '\\u{1F604}'")); eval(t.TEST("re3.lastIndex === 2")); }, // Buffer tests function test_execBuffer(t) { "use strict"; var re = new RE2("охотник\\s(желает).+?(где)", "ig"); var buf = new Buffer("Каждый Охотник Желает Знать Где Сидит Фазан"); var result = re.exec(buf); eval(t.TEST("result.length === 3")); eval(t.TEST("result[0] instanceof Buffer")); eval(t.TEST("result[1] instanceof Buffer")); eval(t.TEST("result[2] instanceof Buffer")); eval(t.TEST("result[0].toString() === 'Охотник Желает Знать Где'")); eval(t.TEST("result[1].toString() === 'Желает'")); eval(t.TEST("result[2].toString() === 'Где'")); eval(t.TEST("result.index === 13")); eval(t.TEST("result.input instanceof Buffer")); eval(t.TEST("result.input.toString() === 'Каждый Охотник Желает Знать Где Сидит Фазан'")); eval(t.TEST("re.lastIndex === 58")); eval(t.TEST("result.input.toString('utf8', result.index) === 'Охотник Желает Знать Где Сидит Фазан'")); eval(t.TEST("result.input.toString('utf8', re.lastIndex) === ' Сидит Фазан'")); }, // Sticky tests function test_execSticky(t) { "use strict"; var re = new RE2("\\s+", "y"); eval(t.TEST("re.exec('Hello world, how are you?') === null")); re.lastIndex = 5; var result = re.exec("Hello world, how are you?"); eval(t.TEST("t.unify(result, [' '])")); eval(t.TEST("result.index === 5")); eval(t.TEST("re.lastIndex === 6")); var re2 = new RE2("\\s+", "gy"); eval(t.TEST("re2.exec('Hello world, how are you?') === null")); re2.lastIndex = 5; var result2 = re2.exec("Hello world, how are you?"); eval(t.TEST("t.unify(result2, [' '])")); eval(t.TEST("result2.index === 5")); eval(t.TEST("re2.lastIndex === 6")); } ]); node-re2-1.10.5/tests/test_general.js000066400000000000000000000135061357256744100174100ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ function test_generalCtr(t) { "use strict"; eval(t.TEST("!!RE2")); eval(t.TEST("RE2.toString() === 'function RE2() { [native code] }'")); eval(t.TEST("!!RE2.prototype")); }, function test_generalInst(t) { "use strict"; var re1 = new RE2("\\d+"); eval(t.TEST("!!re1")); eval(t.TEST("re1 instanceof RE2")); var re2 = RE2("\\d+"); eval(t.TEST("!!re2")); eval(t.TEST("re2 instanceof RE2")); compare(re1, re2, t); re1 = new RE2("\\d+", "m"); eval(t.TEST("!!re1")); eval(t.TEST("re1 instanceof RE2")); re2 = RE2("\\d+", "m"); eval(t.TEST("!!re2")); eval(t.TEST("re2 instanceof RE2")); compare(re1, re2, t); }, function test_instErrors(t) { try { var re = new RE2([]); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e instanceof TypeError")); } try { var re = new RE2({}); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e instanceof TypeError")); } try { var re = new RE2(new Date()); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e instanceof TypeError")); } try { var re = new RE2(null); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e instanceof TypeError")); } try { var re = new RE2(); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e instanceof TypeError")); } try { var re = RE2(); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e instanceof TypeError")); } try { var re = RE2({ toString() { throw "corner"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e instanceof TypeError")); } }, function test_generalIn(t) { "use strict"; var re = new RE2("\\d+"); eval(t.TEST("'exec' in re")); eval(t.TEST("'test' in re")); eval(t.TEST("'match' in re")); eval(t.TEST("'replace' in re")); eval(t.TEST("'search' in re")); eval(t.TEST("'split' in re")); eval(t.TEST("'source' in re")); eval(t.TEST("'flags' in re")); eval(t.TEST("'global' in re")); eval(t.TEST("'ignoreCase' in re")); eval(t.TEST("'multiline' in re")); eval(t.TEST("'sticky' in re")); eval(t.TEST("'lastIndex' in re")); }, function test_generalPresent(t) { "use strict"; var re = new RE2("\\d+"); eval(t.TEST("typeof re.exec == 'function'")); eval(t.TEST("typeof re.test == 'function'")); eval(t.TEST("typeof re.match == 'function'")); eval(t.TEST("typeof re.replace == 'function'")); eval(t.TEST("typeof re.search == 'function'")); eval(t.TEST("typeof re.split == 'function'")); eval(t.TEST("typeof re.source == 'string'")); eval(t.TEST("typeof re.flags == 'string'")); eval(t.TEST("typeof re.global == 'boolean'")); eval(t.TEST("typeof re.ignoreCase == 'boolean'")); eval(t.TEST("typeof re.multiline == 'boolean'")); eval(t.TEST("typeof re.sticky == 'boolean'")); eval(t.TEST("typeof re.lastIndex == 'number'")); }, function test_generalLastIndex(t) { "use strict"; var re = new RE2("\\d+"); eval(t.TEST("re.lastIndex === 0")); re.lastIndex = 5; eval(t.TEST("re.lastIndex === 5")); re.lastIndex = 0; eval(t.TEST("re.lastIndex === 0")); }, function test_generalRegExp(t) { "use strict"; var re1 = new RegExp("\\d+"); var re2 = new RE2("\\d+"); compare(re1, re2, t); re2 = new RE2(re1); compare(re1, re2, t); re1 = new RegExp("a", "ig"); re2 = new RE2("a", "ig"); compare(re1, re2, t); re2 = new RE2(re1); compare(re1, re2, t); re1 = /\s/gm; re2 = new RE2("\\s", "mg"); compare(re1, re2, t); re2 = new RE2(re1); compare(re1, re2, t); re2 = new RE2(/\s/gm); compare(/\s/gm, re2, t); re1 = new RE2("b", "gm"); re2 = new RE2(re1); compare(re1, re2, t); }, function test_utf8(t) { "use strict"; var s = "Привет!"; eval(t.TEST("s.length === 7")); eval(t.TEST("RE2.getUtf8Length(s) === 13")); var b = new Buffer(s); eval(t.TEST("b.length === 13")); eval(t.TEST("RE2.getUtf16Length(b) === 7")); var s2 = "\u{1F603}"; eval(t.TEST("s2.length === 2")); eval(t.TEST("RE2.getUtf8Length(s2) === 4")); var b2 = new Buffer(s2); eval(t.TEST("b2.length === 4")); eval(t.TEST("RE2.getUtf16Length(b2) === 2")); var s3 = "\uD83D"; eval(t.TEST("s3.length === 1")); eval(t.TEST("RE2.getUtf8Length(s3) === 3")); var b3 = new Buffer([0xF0]); eval(t.TEST("b3.length === 1")); eval(t.TEST("RE2.getUtf16Length(b3) === 2")); try { RE2.getUtf8Length({ toString() { throw "corner"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner'")); } eval(t.TEST("RE2.getUtf16Length({ toString() { throw 'corner'; } }) === -1")); }, function test_flags(t) { "use strict"; var re = new RE2("a", "u"); eval(t.TEST("re.flags === 'u'")); re = new RE2("a", "iu"); eval(t.TEST("re.flags === 'iu'")); re = new RE2("a", "mu"); eval(t.TEST("re.flags === 'mu'")); re = new RE2("a", "gu"); eval(t.TEST("re.flags === 'gu'")); re = new RE2("a", "yu"); eval(t.TEST("re.flags === 'uy'")); re = new RE2("a", "yiu"); eval(t.TEST("re.flags === 'iuy'")); re = new RE2("a", "yigu"); eval(t.TEST("re.flags === 'giuy'")); re = new RE2("a", "miu"); eval(t.TEST("re.flags === 'imu'")); re = new RE2("a", "ygu"); eval(t.TEST("re.flags === 'guy'")); re = new RE2("a", "myu"); eval(t.TEST("re.flags === 'muy'")); re = new RE2("a", "migyu"); eval(t.TEST("re.flags === 'gimuy'")); } ]); // utilitites function compare(re1, re2, t) { // compares regular expression objects eval(t.TEST("re1.source === re2.source")); eval(t.TEST("re1.global === re2.global")); eval(t.TEST("re1.ignoreCase === re2.ignoreCase")); eval(t.TEST("re1.multiline === re2.multiline")); // eval(t.TEST("re1.unicode === re2.unicode")); eval(t.TEST("re1.sticky === re2.sticky")); } node-re2-1.10.5/tests/test_groups.js000066400000000000000000000054121357256744100173070ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ function test_groupsNormal(t) { "use strict"; eval(t.TEST("RE2('(?\\\\d)').test('9')")); eval(t.TEST("t.unify(RE2('(?-)', 'g').match('a-b-c'), ['-', '-'])")); eval(t.TEST("t.unify(RE2('(?-)').split('a-b-c'), ['a', '-', 'b', '-', 'c'])")); eval(t.TEST("RE2('(?-)', 'g').search('a-b-c') === 1")); }, function test_groupsExec(t) { "use strict"; var result = new RE2('(\\d)').exec('k9'); eval(t.TEST("result")); eval(t.TEST("result[0] === '9'")); eval(t.TEST("result[1] === '9'")); eval(t.TEST("result.index === 1")); eval(t.TEST("result.input === 'k9'")); eval(t.TEST("typeof result.groups == 'undefined'")); result = new RE2('(?\\d)').exec('k9'); eval(t.TEST("result")); eval(t.TEST("result[0] === '9'")); eval(t.TEST("result[1] === '9'")); eval(t.TEST("result.index === 1")); eval(t.TEST("result.input === 'k9'")); eval(t.TEST("t.unify(result.groups, {a: '9'})")); }, function test_groupsMatch(t) { "use strict"; var result = new RE2('(\\d)').match('k9'); eval(t.TEST("result")); eval(t.TEST("result[0] === '9'")); eval(t.TEST("result[1] === '9'")); eval(t.TEST("result.index === 1")); eval(t.TEST("result.input === 'k9'")); eval(t.TEST("typeof result.groups == 'undefined'")); result = new RE2('(?\\d)').match('k9'); eval(t.TEST("result")); eval(t.TEST("result[0] === '9'")); eval(t.TEST("result[1] === '9'")); eval(t.TEST("result.index === 1")); eval(t.TEST("result.input === 'k9'")); eval(t.TEST("t.unify(result.groups, {a: '9'})")); }, function test_groupsMatch(t) { "use strict"; eval(t.TEST("RE2('(?\\\\w)(?\\\\d)', 'g').replace('a1b2c', '$2$1') === '1a2bc'")); eval(t.TEST("RE2('(?\\\\w)(?\\\\d)', 'g').replace('a1b2c', '$$') === '1a2bc'")); eval(t.TEST("RE2('(?\\\\w)(?\\\\d)', 'g').replace('a1b2c', replacerByNumbers) === '1a2bc'")); eval(t.TEST("RE2('(?\\\\w)(?\\\\d)', 'g').replace('a1b2c', replacerByNames) === '1a2bc'")); function replacerByNumbers(match, group1, group2, index, source, groups) { return group2 + group1; } function replacerByNames(match, group1, group2, index, source, groups) { return groups.d + groups.w; } }, function test_groupsInvalid(t) { "use strict"; try { RE2('(?<>.)'); t.test(false); // shouldn'be here } catch(e) { eval(t.TEST("e instanceof SyntaxError")); } // TODO: do we need to enforce the correct id? // try { // RE2('(?<1>.)'); // t.test(false); // shouldn'be here // } catch(e) { // eval(t.TEST("e instanceof SyntaxError")); // } try { RE2('(?.)(?.)'); t.test(false); // shouldn'be here } catch(e) { eval(t.TEST("e instanceof SyntaxError")); } } ]); node-re2-1.10.5/tests/test_invalid.js000066400000000000000000000015631357256744100174210ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ function test_inval(t) { "use strict"; var threw; // Backreferences threw = false; try { new RE2(/(a)\1/); } catch (e) { threw = true; eval(t.TEST("e instanceof SyntaxError")); eval(t.TEST("e.message === 'invalid escape sequence: \\\\1'")); } t.test(threw); // Lookahead assertions // Positive threw = false; try { new RE2(/a(?=b)/); } catch (e) { threw = true; eval(t.TEST("e instanceof SyntaxError")); eval(t.TEST("e.message === 'invalid perl operator: (?='")); } t.test(threw); // Negative threw = false; try { new RE2(/a(?!b)/); } catch (e) { threw = true; eval(t.TEST("e instanceof SyntaxError")); eval(t.TEST("e.message === 'invalid perl operator: (?!'")); } t.test(threw); }, ]); node-re2-1.10.5/tests/test_match.js000066400000000000000000000066041357256744100170700ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ // These tests are copied from MDN: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match function test_match(t) { "use strict"; var str = "For more information, see Chapter 3.4.5.1"; var re = new RE2(/(chapter \d+(\.\d)*)/i); var result = re.match(str); eval(t.TEST("result.input === str")); eval(t.TEST("result.index === 26")); eval(t.TEST("result.length === 3")); eval(t.TEST("result[0] === 'Chapter 3.4.5.1'")); eval(t.TEST("result[1] === 'Chapter 3.4.5.1'")); eval(t.TEST("result[2] === '.1'")); }, function test_matchGlobal(t) { "use strict"; var re = new RE2(/[A-E]/gi); var result = re.match("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); eval(t.TEST("t.unify(result, ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e'])")); }, function test_matchFail(t) { "use strict"; var re = new RE2("(a+)?(b+)?"); var result = re.match("aaabb"); eval(t.TEST("result[1] === 'aaa'")); eval(t.TEST("result[2] === 'bb'")); result = re.match("aaacbb"); eval(t.TEST("result[1] === 'aaa'")); eval(t.TEST("result[2] === undefined")); }, function test_matchInvalid(t) { "use strict"; var re = RE2(''); try { re.match({ toString() { throw "corner"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner'")); } }, // Unicode tests function test_matchUnicode(t) { "use strict"; var str = "Это ГЛАВА 3.4.5.1"; var re = new RE2(/(глава \d+(\.\d)*)/i); var result = re.match(str); eval(t.TEST("result.input === str")); eval(t.TEST("result.index === 4")); eval(t.TEST("result.length === 3")); eval(t.TEST("result[0] === 'ГЛАВА 3.4.5.1'")); eval(t.TEST("result[1] === 'ГЛАВА 3.4.5.1'")); eval(t.TEST("result[2] === '.1'")); }, // Buffer tests function test_matchBuffer(t) { "use strict"; var buf = new Buffer("Это ГЛАВА 3.4.5.1"); var re = new RE2(/(глава \d+(\.\d)*)/i); var result = re.match(buf); eval(t.TEST("result.input instanceof Buffer")); eval(t.TEST("result.length === 3")); eval(t.TEST("result[0] instanceof Buffer")); eval(t.TEST("result[1] instanceof Buffer")); eval(t.TEST("result[2] instanceof Buffer")); eval(t.TEST("result.input === buf")); eval(t.TEST("result.index === 7")); eval(t.TEST("result.input.toString('utf8', result.index) === 'ГЛАВА 3.4.5.1'")); eval(t.TEST("result[0].toString() === 'ГЛАВА 3.4.5.1'")); eval(t.TEST("result[1].toString() === 'ГЛАВА 3.4.5.1'")); eval(t.TEST("result[2].toString() === '.1'")); }, // Sticky tests function test_matchSticky(t) { "use strict"; var re = new RE2("\\s+", "y"); eval(t.TEST("re.match('Hello world, how are you?') === null")); re.lastIndex = 5; var result = re.match("Hello world, how are you?"); eval(t.TEST("t.unify(result, [' '])")); eval(t.TEST("result.index === 5")); eval(t.TEST("re.lastIndex === 6")); var re2 = new RE2("\\s+", "gy"); eval(t.TEST("re2.match('Hello world, how are you?') === null")); re2.lastIndex = 5; eval(t.TEST("re2.match('Hello world, how are you?') === null")); var re3 = new RE2(/[A-E]/giy); var result3 = re3.match("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); eval(t.TEST("t.unify(result3, ['A', 'B', 'C', 'D', 'E'])")); } ]); node-re2-1.10.5/tests/test_new.js000066400000000000000000000024471357256744100165660ustar00rootroot00000000000000"use strict"; const unit = require("heya-unit"); const RE2 = require("../re2"); // tests unit.add(module, [ function test_newUnicodeWarnOnce(t) { "use strict"; let errorMessage = null; const consoleError = console.error; console.error = msg => (errorMessage = msg); RE2.unicodeWarningLevel = "warnOnce"; let a = new RE2(".*"); eval(t.TEST("errorMessage")); errorMessage = null; a = new RE2(".?"); eval(t.TEST("errorMessage === null")); RE2.unicodeWarningLevel = "warnOnce"; a = new RE2(".+"); eval(t.TEST("errorMessage")); RE2.unicodeWarningLevel = "nothing"; console.error = consoleError; }, function test_newUnicodeWarn(t) { "use strict"; let errorMessage = null; const consoleError = console.error; console.error = msg => (errorMessage = msg); RE2.unicodeWarningLevel = "warn"; let a = new RE2(".*"); eval(t.TEST("errorMessage")); errorMessage = null; a = new RE2(".?"); eval(t.TEST("errorMessage")); RE2.unicodeWarningLevel = "nothing"; console.error = consoleError; }, function test_newUnicodeWarn(t) { "use strict"; RE2.unicodeWarningLevel = "throw"; try { let a = new RE2("."); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e instanceof SyntaxError")); } RE2.unicodeWarningLevel = "nothing"; } ]); node-re2-1.10.5/tests/test_prototype.js000066400000000000000000000010441357256744100200320ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ function test_prototype(t) { "use strict"; eval(t.TEST("RE2.prototype.source === '(?:)'")); eval(t.TEST("RE2.prototype.flags === ''")); eval(t.TEST("RE2.prototype.global === undefined")); eval(t.TEST("RE2.prototype.ignoreCase === undefined")); eval(t.TEST("RE2.prototype.multiline === undefined")); eval(t.TEST("RE2.prototype.sticky === undefined")); eval(t.TEST("RE2.prototype.lastIndex === undefined")); } ]); node-re2-1.10.5/tests/test_replace.js000066400000000000000000000163101357256744100174020ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ // These tests are copied from MDN: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace function test_replaceString(t) { "use strict"; var re = new RE2(/apples/gi); var result = re.replace("Apples are round, and apples are juicy.", "oranges"); eval(t.TEST("result === 'oranges are round, and oranges are juicy.'")); re = new RE2(/xmas/i); result = re.replace("Twas the night before Xmas...", "Christmas"); eval(t.TEST("result === 'Twas the night before Christmas...'")); re = new RE2(/(\w+)\s(\w+)/); result = re.replace("John Smith", "$2, $1"); eval(t.TEST("result === 'Smith, John'")); }, function test_replaceFunReplacer(t) { "use strict"; function replacer(match, p1, p2, p3, offset, string) { // p1 is nondigits, p2 digits, and p3 non-alphanumerics return [p1, p2, p3].join(' - '); } var re = new RE2(/([^\d]*)(\d*)([^\w]*)/); var result = re.replace("abc12345#$*%", replacer); eval(t.TEST("result === 'abc - 12345 - #$*%'")); }, function test_replaceFunUpper(t) { "use strict"; function upperToHyphenLower(match) { return '-' + match.toLowerCase(); } var re = new RE2(/[A-Z]/g); var result = re.replace("borderTop", upperToHyphenLower); eval(t.TEST("result === 'border-top'")); }, function test_replaceFunConvert(t) { "use strict"; function convert(str, p1, offset, s) { return ((p1 - 32) * 5/9) + 'C'; } var re = new RE2(/(\d+(?:\.\d*)?)F\b/g); eval(t.TEST("re.replace('32F', convert) === '0C'")); eval(t.TEST("re.replace('41F', convert) === '5C'")); eval(t.TEST("re.replace('50F', convert) === '10C'")); eval(t.TEST("re.replace('59F', convert) === '15C'")); eval(t.TEST("re.replace('68F', convert) === '20C'")); eval(t.TEST("re.replace('77F', convert) === '25C'")); eval(t.TEST("re.replace('86F', convert) === '30C'")); eval(t.TEST("re.replace('95F', convert) === '35C'")); eval(t.TEST("re.replace('104F', convert) === '40C'")); eval(t.TEST("re.replace('113F', convert) === '45C'")); eval(t.TEST("re.replace('212F', convert) === '100C'")); }, { test: function test_replaceFunLoop(t) { "use strict"; RE2(/(x_*)|(-)/g).replace("x-x_", function(match, p1, p2) { if (p1) { t.info("on: " + p1.length); } if (p2) { t.info("off: 1"); } }); }, logs: [ {text: "on: 1"}, {text: "off: 1"}, {text: "on: 2"} ] }, function test_replaceInvalid(t) { "use strict"; var re = RE2(''); try { re.replace({ toString() { throw "corner1"; } }, ''); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner1'")); } try { re.replace('', { toString() { throw "corner2"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner2'")); } var arg2Stringified = false; try { re.replace({ toString() { throw "corner1"; } }, { toString() { arg2Stringified = true; throw "corner2"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner1'")); eval(t.TEST("!arg2Stringified")); } try { re.replace('', () => { throw "corner2"; }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner2'")); } try { re.replace('', () => ({ toString() { throw "corner2"; } })); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner2'")); } }, // Unicode tests function test_replaceStrUnicode(t) { "use strict"; var re = new RE2(/яблоки/gi); var result = re.replace("Яблоки красны, яблоки сочны.", "апельсины"); eval(t.TEST("result === 'апельсины красны, апельсины сочны.'")); re = new RE2(/иван/i); result = re.replace("Могуч Иван Иванов...", "Сидор"); eval(t.TEST("result === 'Могуч Сидор Иванов...'")); re = new RE2(/иван/ig); result = re.replace("Могуч Иван Иванов...", "Сидор"); eval(t.TEST("result === 'Могуч Сидор Сидоров...'")); re = new RE2(/([а-яё]+)\s+([а-яё]+)/i); result = re.replace("Пётр Петров", "$2, $1"); eval(t.TEST("result === 'Петров, Пётр'")); }, function test_replaceFunUnicode(t) { "use strict"; function replacer(match, offset, string) { t.test(typeof offset == "number"); t.test(typeof string == "string"); t.test(offset === 0 || offset === 7); t.test(string === "ИВАН и пЁтр"); return match.charAt(0).toUpperCase() + match.substr(1).toLowerCase(); } var re = new RE2(/(?:иван|пётр|сидор)/ig); var result = re.replace("ИВАН и пЁтр", replacer); eval(t.TEST("result === 'Иван и Пётр'")); }, // Buffer tests function test_replaceStrBuffer(t) { "use strict"; var re = new RE2(/яблоки/gi); var result = re.replace(new Buffer("Яблоки красны, яблоки сочны."), "апельсины"); eval(t.TEST("result instanceof Buffer")); eval(t.TEST("result.toString() === 'апельсины красны, апельсины сочны.'")); result = re.replace(new Buffer("Яблоки красны, яблоки сочны."), new Buffer("апельсины")); eval(t.TEST("result instanceof Buffer")); eval(t.TEST("result.toString() === 'апельсины красны, апельсины сочны.'")); result = re.replace("Яблоки красны, яблоки сочны.", new Buffer("апельсины")); eval(t.TEST("typeof result == 'string'")); eval(t.TEST("result === 'апельсины красны, апельсины сочны.'")); }, function test_replaceFunBuffer(t) { "use strict"; function replacer(match, offset, string) { eval(t.TEST("match instanceof Buffer")); eval(t.TEST("typeof offset == 'number'")); eval(t.TEST("typeof string == 'string'")); eval(t.TEST("offset === 0 || offset === 12")); eval(t.TEST("string === 'ИВАН и пЁтр'")); var s = match.toString(); return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase(); } replacer.useBuffers = true; var re = new RE2(/(?:иван|пётр|сидор)/ig); var result = re.replace("ИВАН и пЁтр", replacer); eval(t.TEST("typeof result == 'string'")); eval(t.TEST("result === 'Иван и Пётр'")); }, // Sticky tests function test_replaceSticky(t) { "use strict"; var re = new RE2(/[A-E]/y); eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === '!BCDEFABCDEF'")); eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'A!CDEFABCDEF'")); eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'AB!DEFABCDEF'")); eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'ABC!EFABCDEF'")); eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'ABCD!FABCDEF'")); eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'ABCDEFABCDEF'")); eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === '!BCDEFABCDEF'")); var re2 = new RE2(/[A-E]/gy); eval(t.TEST("re2.replace('ABCDEFABCDEF', '!') === '!!!!!FABCDEF'")); eval(t.TEST("re2.replace('FABCDEFABCDE', '!') === 'FABCDEFABCDE'")); re2.lastIndex = 3; eval(t.TEST("re2.replace('ABCDEFABCDEF', '!') === '!!!!!FABCDEF'")); eval(t.TEST("re2.lastIndex === 0")); } ]); node-re2-1.10.5/tests/test_search.js000066400000000000000000000042041357256744100172330ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ function test_search(t) { "use strict"; var str = "Total is 42 units."; var re = new RE2(/\d+/i); var result = re.search(str); eval(t.TEST("result === 9")); re = new RE2("\\b[a-z]+\\b"); result = re.search(str); eval(t.TEST("result === 6")); re = new RE2("\\b\\w+\\b"); result = re.search(str); eval(t.TEST("result === 0")); re = new RE2("z", "gm"); result = re.search(str); eval(t.TEST("result === -1")); }, function test_searchInvalid(t) { "use strict"; var re = RE2(''); try { re.search({ toString() { throw "corner"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner'")); } }, function test_searchUnicode(t) { "use strict"; var str = "Всего 42 штуки."; var re = new RE2(/\d+/i); var result = re.search(str); eval(t.TEST("result === 6")); re = new RE2("\\s[а-я]+"); result = re.search(str); eval(t.TEST("result === 8")); re = new RE2("[а-яА-Я]+"); result = re.search(str); eval(t.TEST("result === 0")); re = new RE2("z", "gm"); result = re.search(str); eval(t.TEST("result === -1")); }, function test_searchBuffer(t) { "use strict"; var buf = new Buffer("Всего 42 штуки."); var re = new RE2(/\d+/i); var result = re.search(buf); eval(t.TEST("result === 11")); re = new RE2("\\s[а-я]+"); result = re.search(buf); eval(t.TEST("result === 13")); re = new RE2("[а-яА-Я]+"); result = re.search(buf); eval(t.TEST("result === 0")); re = new RE2("z", "gm"); result = re.search(buf); eval(t.TEST("result === -1")); }, function test_searchSticky(t) { "use strict"; var str = "Total is 42 units."; var re = new RE2(/\d+/y); var result = re.search(str); eval(t.TEST("result === -1")); re = new RE2("\\b[a-z]+\\b", "y"); result = re.search(str); eval(t.TEST("result === -1")); re = new RE2("\\b\\w+\\b", "y"); result = re.search(str); eval(t.TEST("result === 0")); re = new RE2("z", "gmy"); result = re.search(str); eval(t.TEST("result === -1")); } ]); node-re2-1.10.5/tests/test_source.js000066400000000000000000000035671357256744100173010ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ function test_sourceIdentity(t) { "use strict"; var re = new RE2("a\\cM\\u34\\u1234\\u10abcdz"); eval(t.TEST("re.source === 'a\\\\cM\\\\u34\\\\u1234\\\\u10abcdz'")); re = new RE2("a\\cM\\u34\\u1234\\u{10abcd}z"); eval(t.TEST("re.source === 'a\\\\cM\\\\u34\\\\u1234\\\\u{10abcd}z'")); re = new RE2(""); eval(t.TEST("re.source === '(?:)'")); re = new RE2("foo/bar"); eval(t.TEST("re.source === 'foo\\\\/bar'")); re = new RE2("foo\\/bar"); eval(t.TEST("re.source === 'foo\\\\/bar'")); re = new RE2("(?bar)", "u"); eval(t.TEST("re.source === '(?bar)'")); }, function test_sourceTranslation(t) { "use strict"; var re = new RE2("a\\cM\\u34\\u1234\\u10abcdz"); eval(t.TEST("re.internalSource === 'a\\\\x0D\\\\x{34}\\\\x{1234}\\\\x{10ab}cdz'")); re = new RE2("a\\cM\\u34\\u1234\\u{10abcd}z"); eval(t.TEST("re.internalSource === 'a\\\\x0D\\\\x{34}\\\\x{1234}\\\\x{10abcd}z'")); re = new RE2(""); eval(t.TEST("re.internalSource === '(?:)'")); re = new RE2("foo/bar"); eval(t.TEST("re.internalSource === 'foo\\\\/bar'")); re = new RE2("foo\\/bar"); eval(t.TEST("re.internalSource === 'foo\\\\/bar'")); re = new RE2("(?bar)", "u"); eval(t.TEST("re.internalSource === '(?Pbar)'")); }, function test_sourceBackSlashes(t) { "use strict"; function compare(source, expected) { var s = new RE2(source).source; eval(t.TEST("s === expected")); } compare("a/b", "a\\/b"); compare("a\/b", "a\\/b"); compare("a\\/b", "a\\/b"); compare("a\\\/b", "a\\/b"); compare("a\\\\/b", "a\\\\\\/b"); compare("a\\\\\/b", "a\\\\\\/b"); compare("/a/b", "\\/a\\/b"); compare("\\/a/b", "\\/a\\/b"); compare("\\/a\\/b", "\\/a\\/b"); compare("\\/a\\\\/b", "\\/a\\\\\\/b"); } ]); node-re2-1.10.5/tests/test_split.js000066400000000000000000000123631357256744100171260ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ // These tests are copied from MDN: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split function test_split(t) { "use strict"; var re = new RE2(/\s+/); var result = re.split("Oh brave new world that has such people in it."); eval(t.TEST("t.unify(result, ['Oh', 'brave', 'new', 'world', 'that', 'has', 'such', 'people', 'in', 'it.'])")); re = new RE2(","); result = re.split("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"); eval(t.TEST("t.unify(result, ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])")); re = new RE2(","); result = re.split(",Jan,Feb,Mar,Apr,May,Jun,,Jul,Aug,Sep,Oct,Nov,Dec,"); eval(t.TEST("t.unify(result, ['','Jan','Feb','Mar','Apr','May','Jun','','Jul','Aug','Sep','Oct','Nov','Dec',''])")); re = new RE2(/\s*;\s*/); result = re.split("Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ;Chris Hand "); eval(t.TEST("t.unify(result, ['Harry Trump', 'Fred Barney', 'Helen Rigby', 'Bill Abel', 'Chris Hand '])")); re = new RE2(/\s+/); result = re.split("Hello World. How are you doing?", 3); eval(t.TEST("t.unify(result, ['Hello', 'World.', 'How'])")); re = new RE2(/(\d)/); result = re.split("Hello 1 word. Sentence number 2."); eval(t.TEST("t.unify(result, ['Hello ', '1', ' word. Sentence number ', '2', '.'])")); eval(t.TEST("RE2(/[x-z]*/).split('asdfghjkl').reverse().join('') === 'lkjhgfdsa'")); }, function test_splitInvalid(t) { "use strict"; var re = RE2(''); try { re.split({ toString() { throw "corner"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner'")); } }, function test_cornerCases(t) { "use strict"; var re = new RE2(/1/); var result = re.split("23456"); eval(t.TEST("t.unify(result, ['23456'])")); }, // Unicode tests function test_splitUnicode(t) { "use strict"; var re = new RE2(/\s+/); var result = re.split("Она не понимает, что этим убивает меня."); eval(t.TEST("t.unify(result, ['Она', 'не', 'понимает,', 'что', 'этим', 'убивает', 'меня.'])")); re = new RE2(","); result = re.split("Пн,Вт,Ср,Чт,Пт,Сб,Вс"); eval(t.TEST("t.unify(result, ['Пн','Вт','Ср','Чт','Пт','Сб','Вс'])")); re = new RE2(/\s*;\s*/); result = re.split("Ваня Иванов ;Петро Петренко; Саша Машин ; Маша Сашина"); eval(t.TEST("t.unify(result, ['Ваня Иванов', 'Петро Петренко', 'Саша Машин', 'Маша Сашина'])")); re = new RE2(/\s+/); result = re.split("Привет мир. Как дела?", 3); eval(t.TEST("t.unify(result, ['Привет', 'мир.', 'Как'])")); re = new RE2(/(\d)/); result = re.split("Привет 1 слово. Предложение номер 2."); eval(t.TEST("t.unify(result, ['Привет ', '1', ' слово. Предложение номер ', '2', '.'])")); eval(t.TEST("RE2(/[э-я]*/).split('фывапролд').reverse().join('') === 'длорпавыф'")); }, // Buffer tests function test_splitBuffer(t) { "use strict"; var re = new RE2(/\s+/); var result = re.split(new Buffer("Она не понимает, что этим убивает меня.")); eval(t.TEST("t.unify(verifyBuffer(result, t), ['Она', 'не', 'понимает,', 'что', 'этим', 'убивает', 'меня.'])")); re = new RE2(","); result = re.split(new Buffer("Пн,Вт,Ср,Чт,Пт,Сб,Вс")); eval(t.TEST("t.unify(verifyBuffer(result, t), ['Пн','Вт','Ср','Чт','Пт','Сб','Вс'])")); re = new RE2(/\s*;\s*/); result = re.split(new Buffer("Ваня Иванов ;Петро Петренко; Саша Машин ; Маша Сашина")); eval(t.TEST("t.unify(verifyBuffer(result, t), ['Ваня Иванов', 'Петро Петренко', 'Саша Машин', 'Маша Сашина'])")); re = new RE2(/\s+/); result = re.split(new Buffer("Привет мир. Как дела?"), 3); eval(t.TEST("t.unify(verifyBuffer(result, t), ['Привет', 'мир.', 'Как'])")); re = new RE2(/(\d)/); result = re.split(new Buffer("Привет 1 слово. Предложение номер 2.")); eval(t.TEST("t.unify(verifyBuffer(result, t), ['Привет ', '1', ' слово. Предложение номер ', '2', '.'])")); eval(t.TEST("RE2(/[э-я]*/).split(new Buffer('фывапролд')).map(function(x) { return x.toString(); }).reverse().join('') === 'длорпавыф'")); }, // Sticky tests function test_splitSticky(t) { "use strict"; var re = new RE2(/\s+/y); // sticky is ignored var result = re.split("Oh brave new world that has such people in it."); eval(t.TEST("t.unify(result, ['Oh', 'brave', 'new', 'world', 'that', 'has', 'such', 'people', 'in', 'it.'])")); var result2 = re.split(" Oh brave new world that has such people in it."); eval(t.TEST("t.unify(result2, ['', 'Oh', 'brave', 'new', 'world', 'that', 'has', 'such', 'people', 'in', 'it.'])")); } ]); function verifyBuffer(buf, t) { return buf.map(function(x) { t.test(x instanceof Buffer); return x.toString(); }); } node-re2-1.10.5/tests/test_symbols.js000066400000000000000000000055121357256744100174610ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ function test_match_symbol (t) { "use strict"; if (typeof Symbol == 'undefined' || !Symbol.match) return; var str = "For more information, see Chapter 3.4.5.1"; var re = new RE2(/(chapter \d+(\.\d)*)/i); var result = str.match(re); eval(t.TEST("result.input === str")); eval(t.TEST("result.index === 26")); eval(t.TEST("result.length === 3")); eval(t.TEST("result[0] === 'Chapter 3.4.5.1'")); eval(t.TEST("result[1] === 'Chapter 3.4.5.1'")); eval(t.TEST("result[2] === '.1'")); }, function test_search_symbol (t) { "use strict"; if (typeof Symbol == 'undefined' || !Symbol.search) return; var str = "Total is 42 units."; var re = new RE2(/\d+/i); var result = str.search(re); eval(t.TEST("result === 9")); re = new RE2("\\b[a-z]+\\b"); result = str.search(re); eval(t.TEST("result === 6")); re = new RE2("\\b\\w+\\b"); result = str.search(re); eval(t.TEST("result === 0")); re = new RE2("z", "gm"); result = str.search(re); eval(t.TEST("result === -1")); }, function test_replace_symbol (t) { "use strict"; if (typeof Symbol == 'undefined' || !Symbol.replace) return; var re = new RE2(/apples/gi); var result = "Apples are round, and apples are juicy.".replace(re, "oranges"); eval(t.TEST("result === 'oranges are round, and oranges are juicy.'")); re = new RE2(/xmas/i); result = "Twas the night before Xmas...".replace(re, "Christmas"); eval(t.TEST("result === 'Twas the night before Christmas...'")); re = new RE2(/(\w+)\s(\w+)/); result = "John Smith".replace(re, "$2, $1"); eval(t.TEST("result === 'Smith, John'")); }, function test_split(t) { "use strict"; if (typeof Symbol == 'undefined' || !Symbol.split) return; var re = new RE2(/\s+/); var result = "Oh brave new world that has such people in it.".split(re); eval(t.TEST("t.unify(result, ['Oh', 'brave', 'new', 'world', 'that', 'has', 'such', 'people', 'in', 'it.'])")); re = new RE2(","); result = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(re); eval(t.TEST("t.unify(result, ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])")); re = new RE2(/\s*;\s*/); result = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ;Chris Hand ".split(re); eval(t.TEST("t.unify(result, ['Harry Trump', 'Fred Barney', 'Helen Rigby', 'Bill Abel', 'Chris Hand '])")); re = new RE2(/\s+/); result = "Hello World. How are you doing?".split(re, 3); eval(t.TEST("t.unify(result, ['Hello', 'World.', 'How'])")); re = new RE2(/(\d)/); result = "Hello 1 word. Sentence number 2.".split(re); eval(t.TEST("t.unify(result, ['Hello ', '1', ' word. Sentence number ', '2', '.'])")); eval(t.TEST("'asdfghjkl'.split(RE2(/[x-z]*/)).reverse().join('') === 'lkjhgfdsa'")); } ]); node-re2-1.10.5/tests/test_test.js000066400000000000000000000127221357256744100167510ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ // These tests are copied from MDN: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test function test_testFromExec(t) { "use strict"; var re = new RE2("quick\\s(brown).+?(jumps)", "i"); eval(t.TEST("re.test('The Quick Brown Fox Jumps Over The Lazy Dog')")); eval(t.TEST("re.test('tHE qUICK bROWN fOX jUMPS oVER tHE lAZY dOG')")); eval(t.TEST("re.test('the quick brown fox jumps over the lazy dog')")); eval(t.TEST("re.test('THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG')")); eval(t.TEST("!re.test('THE KWIK BROWN FOX JUMPS OVER THE LAZY DOG')")); re = new RE2("ab*", "g"); eval(t.TEST("re.test('abbcdefabh')")); eval(t.TEST("!re.test('qwerty')")); re = new RE2("(hello \\S+)"); eval(t.TEST("re.test('This is a hello world!')")); eval(t.TEST("!re.test('This is a Hello world!')")); }, function test_testSucc(t) { "use strict"; var str = "abbcdefabh"; var re = new RE2("ab*", "g"); var result = re.test(str); eval(t.TEST("result")); eval(t.TEST("re.lastIndex === 3")); result = re.test(str); eval(t.TEST("result")); eval(t.TEST("re.lastIndex === 9")); result = re.test(str); eval(t.TEST("!result")); }, function test_testSimple(t) { "use strict"; var str = "abbcdefabh"; var re1 = new RE2("ab*", "g"); eval(t.TEST("re1.test(str)")); var re2 = new RE2("ab*"); eval(t.TEST("re2.test(str)")); var re3 = new RE2("abc"); eval(t.TEST("!re3.test(str)")); }, function test_testAnchoredToBeginning(t) { "use strict"; var re = RE2('^hello', 'g'); eval(t.TEST("re.test('hellohello')")); eval(t.TEST("!re.test('hellohello')")); }, function test_testInvalid(t) { "use strict"; var re = RE2(''); try { re.test({ toString() { throw "corner"; } }); t.test(false); // shouldn't be here } catch(e) { eval(t.TEST("e === 'corner'")); } }, function test_testAnchor1(t) { "use strict"; var re = new RE2("b|^a", "g"); var result = re.test("aabc"); eval(t.TEST("result")); eval(t.TEST("re.lastIndex === 1")); result = re.test("aabc"); eval(t.TEST("result")); eval(t.TEST("re.lastIndex === 3")); result = re.test("aabc"); eval(t.TEST("!result")); }, function test_testAnchor2(t) { "use strict"; var re = new RE2("(?:^a)", "g"); var result = re.test("aabc"); eval(t.TEST("result")); eval(t.TEST("re.lastIndex === 1")); result = re.test("aabc"); eval(t.TEST("!result")); }, // Unicode tests function test_testUnicode(t) { "use strict"; var re = new RE2("охотник\\s(желает).+?(где)", "i"); eval(t.TEST("re.test('Каждый Охотник Желает Знать Где Сидит Фазан')")); eval(t.TEST("re.test('кАЖДЫЙ оХОТНИК жЕЛАЕТ зНАТЬ гДЕ сИДИТ фАЗАН')")); eval(t.TEST("re.test('каждый охотник желает знать где сидит фазан')")); eval(t.TEST("re.test('КАЖДЫЙ ОХОТНИК ЖЕЛАЕТ ЗНАТЬ ГДЕ СИДИТ ФАЗАН')")); eval(t.TEST("!re.test('Кажный Стрелок Хочет Найти Иде Прячется Птица')")); re = new RE2("аб*", "g"); eval(t.TEST("re.test('аббвгдеабё')")); eval(t.TEST("!re.test('йцукен')")); re = new RE2("(привет \\S+)"); eval(t.TEST("re.test('Это просто привет всем.')")); eval(t.TEST("!re.test('Это просто Привет всем.')")); }, function test_testUnicodeSubsequent(t) { "use strict"; var str = "аббвгдеабё"; var re = new RE2("аб*", "g"); var result = re.test(str); eval(t.TEST("result")); eval(t.TEST("re.lastIndex === 3")); result = re.test(str); eval(t.TEST("result")); eval(t.TEST("re.lastIndex === 9")); result = re.test(str); eval(t.TEST("!result")); }, // Buffer tests function test_testBuffer(t) { "use strict"; var re = new RE2("охотник\\s(желает).+?(где)", "i"); eval(t.TEST("re.test(new Buffer('Каждый Охотник Желает Знать Где Сидит Фазан'))")); eval(t.TEST("re.test(new Buffer('кАЖДЫЙ оХОТНИК жЕЛАЕТ зНАТЬ гДЕ сИДИТ фАЗАН'))")); eval(t.TEST("re.test(new Buffer('каждый охотник желает знать где сидит фазан'))")); eval(t.TEST("re.test(new Buffer('КАЖДЫЙ ОХОТНИК ЖЕЛАЕТ ЗНАТЬ ГДЕ СИДИТ ФАЗАН'))")); eval(t.TEST("!re.test(new Buffer('Кажный Стрелок Хочет Найти Иде Прячется Птица'))")); re = new RE2("аб*", "g"); eval(t.TEST("re.test(new Buffer('аббвгдеабё'))")); eval(t.TEST("!re.test(new Buffer('йцукен'))")); re = new RE2("(привет \\S+)"); eval(t.TEST("re.test(new Buffer('Это просто привет всем.'))")); eval(t.TEST("!re.test(new Buffer('Это просто Привет всем.'))")); }, // Sticky tests function test_testSticky(t) { "use strict"; var re = new RE2("\\s+", "y"); eval(t.TEST("!re.test('Hello world, how are you?')")); re.lastIndex = 5; eval(t.TEST("re.test('Hello world, how are you?')")); eval(t.TEST("re.lastIndex === 6")); var re2 = new RE2("\\s+", "gy"); eval(t.TEST("!re2.test('Hello world, how are you?')")); re2.lastIndex = 5; eval(t.TEST("re2.test('Hello world, how are you?')")); eval(t.TEST("re2.lastIndex === 6")); } ]); node-re2-1.10.5/tests/test_toString.js000066400000000000000000000017721357256744100176060ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); var RE2 = require("../re2"); // tests unit.add(module, [ function test_toString(t) { "use strict"; eval(t.TEST("RE2('').toString() === '/(?:)/u'")); eval(t.TEST("RE2('a').toString() === '/a/u'")); eval(t.TEST("RE2('b', 'i').toString() === '/b/iu'")); eval(t.TEST("RE2('c', 'g').toString() === '/c/gu'")); eval(t.TEST("RE2('d', 'm').toString() === '/d/mu'")); eval(t.TEST("RE2('\\\\d+', 'gi') + '' === '/\\\\d+/giu'")); eval(t.TEST("RE2('\\\\s*', 'gm') + '' === '/\\\\s*/gmu'")); eval(t.TEST("RE2('\\\\S{1,3}', 'ig') + '' === '/\\\\S{1,3}/giu'")); eval(t.TEST("RE2('\\\\D{,2}', 'mig') + '' === '/\\\\D{,2}/gimu'")); eval(t.TEST("RE2('^a{2,}', 'mi') + '' === '/^a{2,}/imu'")); eval(t.TEST("RE2('^a{5}$', 'gim') + '' === '/^a{5}$/gimu'")); eval(t.TEST("RE2('\\\\u{1F603}/', 'iy') + '' === '/\\\\x{1F603}\\\\//iuy'")); eval(t.TEST("RE2('c', 'ug').toString() === '/c/gu'")); eval(t.TEST("RE2('d', 'um').toString() === '/d/mu'")); } ]); node-re2-1.10.5/tests/tests.js000066400000000000000000000006531357256744100160750ustar00rootroot00000000000000"use strict"; var unit = require("heya-unit"); require("./test_general"); require("./test_source"); require("./test_exec"); require("./test_test"); require("./test_toString"); require("./test_match"); require("./test_replace"); require("./test_search"); require("./test_split"); require("./test_invalid"); require("./test_symbols"); require("./test_prototype"); require("./test_new"); require("./test_groups"); unit.run(); node-re2-1.10.5/vendor/000077500000000000000000000000001357256744100145245ustar00rootroot00000000000000