/* * Based on code from: * * XRegExp 1.5.0 * (c) 2007-2010 Steven Levithan * MIT License * * Provides an augmented, extensible, cross-browser implementation of regular expressions, * including support for additional syntax, flags, and methods */ define(function(require, exports, module) { "use strict"; //--------------------------------- // Private variables //--------------------------------- var real = { exec: RegExp.prototype.exec, test: RegExp.prototype.test, match: String.prototype.match, replace: String.prototype.replace, split: String.prototype.split }, compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups compliantLastIndexIncrement = function () { var x = /^/g; real.test.call(x, ""); return !x.lastIndex; }(); if (compliantLastIndexIncrement && compliantExecNpcg) return; //--------------------------------- // Overriden native methods //--------------------------------- // Adds named capture support (with backreferences returned as `result.name`), and fixes two // cross-browser issues per ES3: // - Captured values for nonparticipating capturing groups should be returned as `undefined`, // rather than the empty string. // - `lastIndex` should not be incremented after zero-length matches. RegExp.prototype.exec = function (str) { var match = real.exec.apply(this, arguments), name, r2; if ( typeof(str) == 'string' && match) { // Fix browsers whose `exec` methods don't consistently return `undefined` for // nonparticipating capturing groups if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed // matching due to characters outside the match real.replace.call(str.slice(match.index), r2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) match[i] = undefined; } }); } // Attach named capture properties if (this._xregexp && this._xregexp.captureNames) { for (var i = 1; i < match.length; i++) { name = this._xregexp.captureNames[i - 1]; if (name) match[name] = match[i]; } } // Fix browsers that increment `lastIndex` after zero-length matches if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) this.lastIndex--; } return match; }; // Don't override `test` if it won't change anything if (!compliantLastIndexIncrement) { // Fix browser bug in native method RegExp.prototype.test = function (str) { // Use the native `exec` to skip some processing overhead, even though the overriden // `exec` would take care of the `lastIndex` fix var match = real.exec.call(this, str); // Fix browsers that increment `lastIndex` after zero-length matches if (match && this.global && !match[0].length && (this.lastIndex > match.index)) this.lastIndex--; return !!match; }; } //--------------------------------- // Private helper functions //--------------------------------- function getNativeFlags (regex) { return (regex.global ? "g" : "") + (regex.ignoreCase ? "i" : "") + (regex.multiline ? "m" : "") + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 (regex.sticky ? "y" : ""); } function indexOf (array, item, from) { if (Array.prototype.indexOf) // Use the native array method if available return array.indexOf(item, from); for (var i = from || 0; i < array.length; i++) { if (array[i] === item) return i; } return -1; } });