Ejemplo n.º 1
0
        public override Completion InternalConstruct(IReadOnlyList <IValue> arguments, Object?newTarget)
        {
            var pattern = arguments.At(0, UndefinedValue.Instance);
            var flags   = arguments.At(1, UndefinedValue.Instance);

            var patternIsRegExpComp = IsRegExp(pattern);

            if (patternIsRegExpComp.IsAbrupt())
            {
                return(patternIsRegExpComp);
            }
            var patternIsRegExp = patternIsRegExpComp.Other;

            if (newTarget == null)
            {
                newTarget = this;
                if (patternIsRegExp && flags == UndefinedValue.Instance)
                {
                    var patternObject      = (pattern as Object) !;
                    var patternConstructor = patternObject.Get("constructor");
                    if (patternConstructor.IsAbrupt())
                    {
                        return(patternConstructor);
                    }
                    if (patternObject == newTarget)
                    {
                        return(Completion.NormalCompletion(pattern));
                    }
                }
            }
            IValue P, F;

            if (pattern is RegExpObject r)
            {
                P = new StringValue(r.OriginalSource);
                if (flags == UndefinedValue.Instance)
                {
                    F = new StringValue(r.OriginalFlags);
                }
                else
                {
                    F = flags;
                }
            }
            else if (patternIsRegExp)
            {
                var patternObject = (pattern as Object) !;
                var PComp         = patternObject.Get("source");
                if (PComp.IsAbrupt())
                {
                    return(PComp);
                }
                P = PComp.value !;
                if (flags == UndefinedValue.Instance)
                {
                    var FComp = patternObject.Get("flags");
                    if (FComp.IsAbrupt())
                    {
                        return(FComp);
                    }
                    F = FComp.value !;
                }
                else
                {
                    F = flags;
                }
            }
            else
            {
                P = pattern;
                F = flags;
            }
            return(RegExpObject.RegExpAllocAndInitialize(P, F));
        }
Ejemplo n.º 2
0
        public override Completion InternalCall(IValue thisValue, IReadOnlyList <IValue> arguments)
        {
            var b = arguments.At(0, UndefinedValue.Instance).ToBoolean();

            return(Completion.NormalCompletion(b));
        }
Ejemplo n.º 3
0
        private Completion CreateDynamicFunction(Object?newTarget, FunctionKind kind, IReadOnlyList <IValue> arguments)
        {
            if (Interpreter.Instance().ExecutionContextStackSize() < 2)
            {
                throw new InvalidOperationException("Spec 19.2.1.1.1 step 1");
            }
            var callerContext = Interpreter.Instance().SecondExecutionContext();
            var callerRealm   = callerContext.Realm;
            var calleeRealm   = Interpreter.Instance().CurrentRealm();

            //TODO HostEnsureCanCompileStrings
            if (newTarget == null)
            {
                newTarget = this;
            }
            Func <Parser.Parser, AST.FunctionStatementList> goal;
            Func <Intrinsics, Object> fallbackProto;

            switch (kind)
            {
            case FunctionKind.Normal:
                goal          = (p) => p.ParseFunctionBody();
                fallbackProto = i => i.FunctionPrototype;
                break;

            default:
                throw new NotImplementedException("Async and/or generators");
            }
            var    argCount = arguments.Count;
            var    P        = "";
            string bodyText;

            if (argCount == 0)
            {
                bodyText = "";
            }
            else if (argCount == 1)
            {
                var bodyComp = arguments[0].ToJsString();
                if (bodyComp.IsAbrupt())
                {
                    return(bodyComp);
                }
                bodyText = (bodyComp.value as StringValue) !.@string;
            }
            else
            {
                var firstArg = arguments[0];
                var pComp    = firstArg.ToJsString();
                if (pComp.IsAbrupt())
                {
                    return(pComp);
                }
                P = (pComp.value as StringValue) !.@string;
                int k = 1;
                for (; k < argCount - 1; k++)
                {
                    var nextArg           = arguments[k];
                    var nextArgStringComp = nextArg.ToJsString();
                    if (nextArgStringComp.IsAbrupt())
                    {
                        return(nextArgStringComp);
                    }
                    var nextArgString = (nextArgStringComp.value as StringValue) !.@string;
                    P += "," + nextArgString;
                }
                var bodyComp = arguments[k].ToJsString();
                if (bodyComp.IsAbrupt())
                {
                    return(bodyComp);
                }
                bodyText = (bodyComp.value as StringValue) !.@string;
            }
            AST.FormalParameters?parameters = new AST.FormalParameters();
            try
            {
                if (!string.IsNullOrEmpty(P))
                {
                    parameters = new Parser.Parser(P).ParseFormalParameters();
                }
                if (parameters == null)
                {
                    throw new Parser.ParseFailureException($"parameters {P} could not be parsed.");
                }
            }
            catch (Parser.ParseFailureException e)
            {
                return(Completion.ThrowSyntaxError($"Failed to parse parameters \"{P}\".\n{e.Message}"));
            }
            AST.FunctionStatementList body;
            try
            {
                body = goal(new Parser.Parser(bodyText));
            }
            catch (Parser.ParseFailureException e)
            {
                return(Completion.ThrowSyntaxError($"Failed to parse body \"{bodyText}\".\n{e.Message}"));
            }
            //TODO detect strict mode: ContainsUseStrict
            bool strict = body.IsStrictMode;

            if (!parameters.IsSimpleParameterList() && strict)
            {
                return(Completion.ThrowSyntaxError($"parameters must be simple in strict mode. \"{P}\""));
            }
            //TODO implement tree walking for checking if parameters or body contains a SuperCall or SuperProperty
            //TODO generator yield, async await errors
            var protoComp = Utils.GetPrototypeFromConstructor(newTarget, fallbackProto);

            if (protoComp.IsAbrupt())
            {
                return(protoComp);
            }
            var proto  = protoComp.value;
            var F      = FunctionObject.FunctionAllocate(proto !, strict, kind);
            var realmF = F.Realm;
            var scope  = realmF.GlobalEnv;

            FunctionObject.FunctionInitialize(F, FunctionCreateKind.Normal, parameters, body, scope);
            //TODO generator, async generator
            if (kind == FunctionKind.Normal)
            {
                F.MakeConstructor();
            }
            F.SetFunctionName("anonymous");
            return(Completion.NormalCompletion(F));
        }
Ejemplo n.º 4
0
        private static Completion RegExpBuiltinExec(RegExpObject R, string S)
        {
            var length = S.Length;
            int lastIndex;
            {
                var lastIndexComp = R.Get("lastIndex");
                if (lastIndexComp.IsAbrupt())
                {
                    return(lastIndexComp);
                }
                var lastIndexLength = lastIndexComp.value !.ToLength();
                if (lastIndexLength.IsAbrupt())
                {
                    return(lastIndexLength);
                }
                lastIndex = (int)lastIndexLength.Other;
            }
            var flags  = R.OriginalFlags;
            var global = flags.Contains('g', StringComparison.Ordinal);
            var sticky = flags.Contains('y', StringComparison.Ordinal);

            if (!global && !sticky)
            {
                lastIndex = 0;
            }
            var   matcher        = R.RegExpMatcher;
            var   fullUnicode    = flags.Contains('u', StringComparison.Ordinal);
            var   matchSucceeded = false;
            Match?r = null;

            while (!matchSucceeded)
            {
                if (lastIndex > length)
                {
                    if (global || sticky)
                    {
                        var set = R.Set("lastIndex", NumberValue.PositiveZero, true);
                        if (set.IsAbrupt())
                        {
                            return(set);
                        }
                    }
                    return(Completion.NormalCompletion(NullValue.Instance));
                }
                r = matcher.Match(S, lastIndex);
                if (!r.Success)
                {
                    if (sticky)
                    {
                        var set = R.Set("lastIndex", NumberValue.PositiveZero, true);
                        if (set.IsAbrupt())
                        {
                            return(set);
                        }
                        return(Completion.NormalCompletion(NullValue.Instance));
                    }
                    lastIndex = AdvanceStringIndex(S, lastIndex, fullUnicode);
                }
                else
                {
                    matchSucceeded = true;
                }
            }

            var e = r !.Index + r.Length;

            if (fullUnicode)
            {
                // e is an index into the Input character list, derived from S, matched by matcher.
                // Let eUTF be the smallest index into S that corresponds to the character at element e of Input.
                // If e is greater than or equal to the number of elements in Input, then eUTF is the number of code units in S.
                // Set e to eUTF.
                var indexes = StringInfo.ParseCombiningCharacters(S);
                if (r.Index < indexes.Length)
                {
                    var sub = StringInfo.GetNextTextElement(S, r.Index);
                    e += sub.Length - 1;
                }
            }
            if (global || sticky)
            {
                var set = R.Set("lastIndex", new NumberValue(e), true);
                if (set.IsAbrupt())
                {
                    return(set);
                }
            }
            var n = r.Groups.Count;
            var A = ArrayObject.ArrayCreate(n + 1);

            Utils.CreateDataProperty(A, "index", new NumberValue(lastIndex));
            Utils.CreateDataProperty(A, "input", new StringValue(S));
            Utils.CreateDataProperty(A, "0", new StringValue(r.Value));
            IValue groups;

            if (R.RegExpMatcher.GetGroupNames().Any())
            {
                groups = Utils.ObjectCreate(null);
            }
            else
            {
                groups = UndefinedValue.Instance;
            }
            Utils.CreateDataProperty(A, "groups", groups);
            for (int i = 0; i <= n; i++)
            {
                var    captureI = r.Groups[i];
                IValue capturedValue;
                if (captureI.Success)
                {
                    if (fullUnicode)
                    {
                        capturedValue = new StringValue(StringInfo.GetNextTextElement(S, captureI.Index));
                    }
                    else
                    {
                        capturedValue = new StringValue(captureI.Value);
                    }
                }
                else
                {
                    capturedValue = UndefinedValue.Instance;
                }
                Utils.CreateDataProperty(A, i.ToString(CultureInfo.InvariantCulture), capturedValue);
                if (!string.IsNullOrEmpty(captureI.Name))
                {
                    Utils.CreateDataProperty(groups, captureI.Name, capturedValue);
                }
            }
            return(Completion.NormalCompletion(A));
        }
Ejemplo n.º 5
0
        public override Completion InternalConstruct(IReadOnlyList <IValue> arguments, Object?newTarget)
        {
            if (newTarget == null)
            {
                newTarget = this;
            }
            var proto = Utils.GetPrototypeFromConstructor(newTarget, i => i.ArrayPrototype);

            if (proto.IsAbrupt())
            {
                return(proto);
            }

            if (arguments.Count == 0)
            {
                return(Completion.NormalCompletion(ArrayObject.ArrayCreate(0, proto.value as Object)));
            }
            else if (arguments.Count == 1)
            {
                var array = ArrayObject.ArrayCreate(0, proto.value as Object);

                int intLen;

                if (!(arguments[0] is NumberValue))
                {
                    var defineStatus = Utils.CreateDataProperty(array, "0", arguments[0]);
                    if (!defineStatus.Other)
                    {
                        throw new InvalidOperationException("CreateDataProperty [0] in array constructor failed. Spec 22.1.1.2 step 6b");
                    }
                    intLen = 1;
                }
                else
                {
                    intLen = (int)(arguments[0] as NumberValue) !.number;
                    if (intLen != (arguments[0] as NumberValue) !.number || intLen < 0)
                    {
                        return(Completion.ThrowRangeError("length argument cannot be used as a length"));
                    }
                }
                array.Set("length", new NumberValue(intLen), true);
                return(Completion.NormalCompletion(array));
            }
            else
            {
                var array = ArrayObject.ArrayCreate(arguments.Count, proto.value as Object);
                int k     = 0;
                foreach (var arg in arguments)
                {
                    var defineStatus = Utils.CreateDataProperty(array, k.ToString(System.Globalization.CultureInfo.InvariantCulture), arg);
                    if (!defineStatus.Other)
                    {
                        throw new InvalidOperationException("CreateDataProperty in array constructor failed. Spec 22.1.1.3 step 8d");
                    }
                    k++;
                }
                if ((array.Get("length").value as NumberValue) !.number != arguments.Count)
                {
                    throw new InvalidOperationException("array length is invalid. Spec 22.1.1.3 step 9");
                }
                return(Completion.NormalCompletion(array));
            }
        }
Ejemplo n.º 6
0
 public JavascriptException(Completion completion) : base(Description(completion))
 {
 }