Example #1
0
        public void Properties()
        {
            EcmaValue iterator = RegExp.Construct(".").Invoke(Symbol.MatchAll, "");
            EcmaValue proto    = Object.Invoke("getPrototypeOf", iterator);

            That(proto, Has.OwnProperty(WellKnownSymbol.ToStringTag, "RegExp String Iterator", EcmaPropertyAttributes.Configurable));
        }
Example #2
0
        public void Constructor(RuntimeFunction ctor)
        {
            IsConstructorWLength(ctor, "RegExp", 2, RegExp.Prototype);

            It("should not throw TypeError when pattern has a [[RegExpMatcher]] internal slot", () => {
                EcmaValue re = RegExp.Construct(RegExp.Construct(), "g");
                That(re["global"], Is.EqualTo(true));
            });

            It("should return its input argument if ToBoolean(@@match) is true and constructor is RegExp", () => {
                EcmaValue obj      = new EcmaObject();
                obj["constructor"] = RegExp;

                obj[WellKnownSymbol.Match] = true;
                Case((RegExp, obj), obj);
                obj[WellKnownSymbol.Match] = "string";
                Case((RegExp, obj), obj);
                obj[WellKnownSymbol.Match] = new EcmaArray();
                Case((RegExp, obj), obj);
                obj[WellKnownSymbol.Match] = new Symbol();
                Case((RegExp, obj), obj);
                obj[WellKnownSymbol.Match] = 86;
                Case((RegExp, obj), obj);

                EcmaValue re1 = RegExp.Construct("(?:)");
                re1[WellKnownSymbol.Match] = false;
                Case((RegExp, re1), Is.Not.EqualTo(re1));

                EcmaValue re2      = RegExp.Construct("(?:)");
                re2["constructor"] = Null;
                Case((RegExp, re2), Is.Not.EqualTo(re2));
            });
Example #3
0
        public void Exec(RuntimeFunction exec)
        {
            IsUnconstructableFunctionWLength(exec, "exec", 1);
            IsAbruptedFromToPrimitive(exec.Bind(RegExp.Construct()));
            RequireThisRegExpObject();

            It("should coerce its argument to string", () => {
                object undefined = Undefined;
                VerifyMatch(@"1|12", "123", new[] { "1" }, 0);
                VerifyMatch(@"1|12", 1.01, new[] { "1" }, 0);
                VerifyMatch(@"2|12", Number.Construct(1.012), new[] { "12" }, 3);
                VerifyMatch(@"\.14", CreateObject(toString: () => EcmaMath.PI), new[] { ".14" }, 1);
                VerifyMatch(@"t[a-b|q-s]", true, new[] { "tr" }, 0);
                VerifyMatch(@"AL|se", Boolean.Construct(), new[] { "se" }, 3);
                VerifyMatch(@"LS", "i", CreateObject(toString: () => false), new[] { "ls" }, 2);
                VerifyMatch(@"ll|l", Null, new[] { "ll" }, 2);
                VerifyMatch(@"nd|ne", Undefined, new[] { "nd" }, 1);
                VerifyMatch(@"((1)|(12))((3)|(23))", String.Construct("123"), new[] { "123", "1", "1", undefined, "23", undefined, "23" }, 0);
                VerifyMatch(@"a[a-z]{2,4}", Object.Construct("abcdefghi"), new[] { "abcde" }, 0);
                VerifyMatch(@"a[a-z]{2,4}?", CreateObject(toString: () => "abcdefghi"), new[] { "abc" }, 0);
                VerifyMatch(@"(aa|aabaac|ba|b|c)*", CreateObject(toString: () => new EcmaObject(), valueOf: () => "aabaac"), new[] { "aaba", "ba" }, 0);
            });

            It("should read and reset lastIndex to 0 when global is set and the match fails", () => {
                EcmaValue re       = RegExp.Construct("a", "g");
                int lastIndexReads = 0;

                re["lastIndex"] = CreateObject(valueOf: () => { lastIndexReads++; return(42); });
                Case((re, "abc"), Null);
                That(re["lastIndex"], Is.EqualTo(0));
                That(lastIndexReads, Is.EqualTo(1));

                lastIndexReads  = 0;
                re["lastIndex"] = CreateObject(valueOf: () => { lastIndexReads++; return(-1); });
                Case((re, "nbc"), Null);
                That(re["lastIndex"], Is.EqualTo(0));
                That(lastIndexReads, Is.EqualTo(1));
            });
Example #4
0
        public static void VerifyMatch(EcmaValue pattern, EcmaValue flags, EcmaValue input, object[] expected, int index)
        {
            EcmaValue re = default;

            That(() => re = RegExp.Construct(pattern, flags), Throws.Nothing, FormatArguments(Undefined, new[] { pattern, flags }));

            RuntimeObject fn = TestContext.CurrentContext.Test.Arguments.FirstOrDefault() as RuntimeObject;

            if (fn == null || fn.IsIntrinsicFunction(WellKnownObject.RegExpPrototype, "test"))
            {
                fn = re.ToObject().GetMethod("exec");
            }
            EcmaValue actual = fn.Call(re, input);

            if (expected != null)
            {
                That(actual, Is.EquivalentTo(expected), "RegExp={0}, Input={1}", re, input);
                That(actual["index"], Is.EqualTo(index), "RegExp={0}, Input={1}", re, input);
            }
            else
            {
                That(actual, Is.EqualTo(Null), "RegExp={0}, Input={1}", re, input);
            }
        }
Example #5
0
        public void Next(RuntimeFunction next)
        {
            IsUnconstructableFunctionWLength(next, "next", 0);

            It("should throw a TypeError if this value does not have all of the internal slots", () => {
                EcmaValue iterator = RegExp.Construct(".").Invoke(Symbol.MatchAll, "");
                That(() => iterator["next"].Call(Undefined), Throws.TypeError);
                That(() => iterator["next"].Call(Null), Throws.TypeError);
                That(() => iterator["next"].Call(1), Throws.TypeError);
                That(() => iterator["next"].Call(false), Throws.TypeError);
                That(() => iterator["next"].Call(""), Throws.TypeError);
                That(() => iterator["next"].Call(new Symbol()), Throws.TypeError);
                That(() => Object.Invoke("create", iterator).Invoke("next"), Throws.TypeError);
            });

            It("should iterate over matches", () => {
                EcmaValue iterator = RegExp.Construct("\\w").Invoke(Symbol.MatchAll, "*a*b*");
                VerifyIteratorResult(iterator.Invoke("next"), false, v => VerifyMatchObject(v, new[] { "a" }, 1, "*a*b*"));
                VerifyIteratorResult(iterator.Invoke("next"), true);

                iterator = RegExp.Construct("\\w", "g").Invoke(Symbol.MatchAll, "*a*b*");
                VerifyIteratorResult(iterator.Invoke("next"), false, v => VerifyMatchObject(v, new[] { "a" }, 1, "*a*b*"));
                VerifyIteratorResult(iterator.Invoke("next"), false, v => VerifyMatchObject(v, new[] { "b" }, 3, "*a*b*"));
                VerifyIteratorResult(iterator.Invoke("next"), true);
            });

            It("should not throw if exec is not callable", () => {
                foreach (EcmaValue value in new[] { Undefined, Null, 4, true, new Symbol() })
                {
                    using (TempProperty(RegExp.Prototype, "exec", value)) {
                        EcmaValue iterator = RegExp.Construct("\\w", "g").Invoke(Symbol.MatchAll, "*a*b*");
                        VerifyIteratorResult(iterator.Invoke("next"), false, v => VerifyMatchObject(v, new[] { "a" }, 1, "*a*b*"));
                        VerifyIteratorResult(iterator.Invoke("next"), false, v => VerifyMatchObject(v, new[] { "b" }, 3, "*a*b*"));
                        VerifyIteratorResult(iterator.Invoke("next"), true);
                    }
                }
            });

            It("should re-throw errors thrown coercing RegExp's lastIndex to a length", () => {
                EcmaValue iterator = RegExp.Construct(".", "g").Invoke(Symbol.MatchAll, "");
                using (TempProperty(RegExp.Prototype, "exec", FunctionLiteral(() =>
                                                                              Return(This.ToObject()["lastIndex"] = CreateObject(valueOf: ThrowTest262Exception), EcmaArray.Of(""))))) {
                    Case(iterator, Throws.Test262);
                }
            });

            It("should return abrupt from calling exec", () => {
                EcmaValue iterator = RegExp.Construct(".").Invoke(Symbol.MatchAll, "");
                using (TempProperty(RegExp.Prototype, "exec", ThrowTest262Exception)) {
                    Case(iterator, Throws.Test262);
                }
            });

            It("should return abrupt from getting exec", () => {
                EcmaValue iterator = RegExp.Construct(".").Invoke(Symbol.MatchAll, "");
                using (TempProperty(RegExp.Prototype, "exec", new EcmaPropertyDescriptor(ThrowTest262Exception, Null))) {
                    Case(iterator, Throws.Test262);
                }
            });

            It("should return abrupt from accessing the first match", () => {
                EcmaValue iterator = RegExp.Construct(".").Invoke(Symbol.MatchAll, "");
                using (TempProperty(RegExp.Prototype, "exec", FunctionLiteral(() => CreateObject((0, get: ThrowTest262Exception, set: null))))) {
                    Case(iterator, Throws.Test262);
                }
            });
Example #6
0
 public static void VerifyMatch(EcmaValue pattern, EcmaValue flags, EcmaValue input, bool success)
 {
     That(RegExp.Construct(pattern, flags).Invoke("test", input), Is.EqualTo(success), FormatArguments(pattern, new[] { input }));
 }
Example #7
0
 public static void Throw(string pattern, string flags)
 {
     That(() => RegExp.Construct(pattern, flags), Throws.SyntaxError, pattern);
 }
Example #8
0
        public void CharacterClassEscape()
        {
            It("should detect a-z, A-Z, 0-9, _ using \\w", () => {
                EcmaValue re     = RegExp.Construct("\\w");
                string wordChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
                string result    = "";
                for (int j = 0x0000; j < 0x10000; j++)
                {
                    EcmaValue str = String.Invoke("fromCharCode", j);
                    if (re.Invoke("test", str))
                    {
                        result += (string)str;
                    }
                }
                That(result, Is.EqualTo(wordChars));
            });

            It("should detect characters other than a-z, A-Z, 0-9, _ using \\W", () => {
                EcmaValue re     = RegExp.Construct("\\W");
                string wordChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
                string result    = "";
                for (int j = 0x0000; j < 0x10000; j++)
                {
                    EcmaValue str = String.Invoke("fromCharCode", j);
                    if (!(bool)re.Invoke("test", str))
                    {
                        result += (string)str;
                    }
                }
                That(result, Is.EqualTo(wordChars));
            });

            It("should detect non WhiteSpace using \\S", () => {
                EcmaValue re          = RegExp.Construct("\\S");
                int[] whitespaceChars = { 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x0020, 0x00A0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F, 0x205F, 0x3000 };
                List <int> result     = new List <int>();
                for (int j = 0x0000; j < 0x10000; j++)
                {
                    if (j == 0x180E)
                    {
                        continue;
                    }                    // Skip 0x180E, current test in a separate file
                    if (j == 0xFEFF)
                    {
                        continue;
                    }                    // Ignore BOM
                    if (!(bool)re.Invoke("test", String.Invoke("fromCharCode", j)))
                    {
                        result.Add(j);
                    }
                }
                That(result, Is.EquivalentTo(whitespaceChars));

                // The Mongolian Vowel Separator (u180e) became a non whitespace character since Unicode 6.3.0
                VerifyMatch(re, "\u180E", true);
            });

            It("should only recognize \\p{name} and \\P{name} escape sequence when [[Unicode]] flag is present", () => {
                VerifyMatch("\\p{Ll}", "a", false);
                VerifyMatch("\\P{Ll}", "A", false);
                VerifyMatch("\\p{Ll}", "u", "a", true);
                VerifyMatch("\\P{Ll}", "u", "A", true);
            });
        }
Example #9
0
        public void ToString(RuntimeFunction toString)
        {
            IsUnconstructableFunctionWLength(toString, "toString", 0);

            EcmaValue obj = new EcmaObject();

            DefineProperty(obj, Symbol.ToStringTag, get: ThrowTest262Exception);
            Case(obj, Throws.Test262);

            EcmaValue args = default;

            FunctionLiteral(() => args = Arguments).Call();
            Case(args, "[object Arguments]");

            Case(new EcmaArray(), "[object Array]");

            Case(true, "[object Boolean]");
            Case(Boolean.Call(_, true), "[object Boolean]");
            Case(Boolean.Construct(true), "[object Boolean]");
            Case(Object.Call(_, true), "[object Boolean]");
            Case(Object.Call(_, Boolean.Call(true)), "[object Boolean]");
            Case(Object.Call(_, Boolean.Construct(true)), "[object Boolean]");

            Case(new EcmaDate(), "[object Date]");
            Case(Object.Call(_, new EcmaDate()), "[object Date]");

            Case(FunctionLiteral(() => Undefined), "[object Function]");

            Case(Null, "[object Null]");

            Case(42, "[object Number]");
            Case(Number.Call(_, 42), "[object Number]");
            Case(Number.Construct(42), "[object Number]");
            Case(Object.Call(_, 42), "[object Number]");
            Case(Object.Call(_, Number.Call(42)), "[object Number]");
            Case(Object.Call(_, Number.Construct(42)), "[object Number]");

            Case(Object.Prototype, "[object Object]");
            Case(new EcmaObject(), "[object Object]");

            Case(RegExp.Construct("."), "[object RegExp]");

            Case("", "[object String]");
            Case(String.Call(_, ""), "[object String]");
            Case(String.Construct(""), "[object String]");
            Case(Object.Call(_, ""), "[object String]");
            Case(Object.Call(_, String.Call("")), "[object String]");
            Case(Object.Call(_, String.Construct("")), "[object String]");

            Case(Undefined, "[object Undefined]");

            Case(Proxy.Construct(Array.Construct(), Object.Construct()), "[object Array]");

            // Non-string values of `@@toStringTag` property are ignored
            Case(CreateObject((Symbol.ToStringTag, Undefined)), "[object Object]");
            Case(CreateObject((Symbol.ToStringTag, Null)), "[object Object]");
            Case(CreateObject((Symbol.ToStringTag, Symbol.ToStringTag)), "[object Object]");
            Case(CreateObject((Symbol.ToStringTag, 42)), "[object Object]");
            Case(CreateObject((Symbol.ToStringTag, String.Construct(""))), "[object Object]");
            Case(CreateObject((Symbol.ToStringTag, new EcmaObject())), "[object Object]");
            Case(CreateObject((Symbol.ToStringTag, FunctionLiteral(() => ""))), "[object Object]");
        }