Esempio n. 1
0
        internal static void AddEntriesFromIterable(ObjectInstance target, IIterator iterable, object adder)
        {
            if (!(adder is ICallable callable))
            {
                ExceptionHelper.ThrowTypeError(target.Engine, "adder must be callable");
                return;
            }

            var args = target.Engine._jsValueArrayPool.RentArray(2);

            var skipClose = true;

            try
            {
                do
                {
                    if (!iterable.TryIteratorStep(out var nextItem))
                    {
                        return;
                    }

                    var temp = nextItem.Get(CommonProperties.Value);

                    skipClose = false;
                    if (!(temp is ObjectInstance oi))
                    {
                        ExceptionHelper.ThrowTypeError(target.Engine, "iterator's value must be an object");
                        return;
                    }

                    var k = oi.Get(JsString.NumberZeroString);
                    var v = oi.Get(JsString.NumberOneString);

                    args[0] = k;
                    args[1] = v;

                    callable.Call(target, args);
                } while (true);
            }
            catch
            {
                if (!skipClose)
                {
                    iterable.Close(CompletionType.Throw);
                }
                throw;
            }
            finally
            {
                target.Engine._jsValueArrayPool.ReturnArray(args);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset
        /// </summary>
        private Completion BodyEvaluation(
            JintExpression lhs,
            JintStatement stmt,
            IIterator iteratorRecord,
            IterationKind iterationKind,
            LhsKind lhsKind,
            IteratorKind iteratorKind = IteratorKind.Sync)
        {
            var    oldEnv        = _engine.ExecutionContext.LexicalEnvironment;
            var    v             = Undefined.Instance;
            var    destructuring = _destructuring;
            string lhsName       = null;

            var completionType = CompletionType.Normal;
            var close          = false;

            try
            {
                while (true)
                {
                    LexicalEnvironment iterationEnv = null;
                    if (!iteratorRecord.TryIteratorStep(out var nextResult))
                    {
                        close = true;
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }

                    if (iteratorKind == IteratorKind.Async)
                    {
                        // nextResult = await nextResult;
                    }

                    var nextValue = nextResult.Get(CommonProperties.Value);
                    close = true;

                    Reference lhsRef = null;
                    if (lhsKind != LhsKind.LexicalBinding)
                    {
                        if (!destructuring)
                        {
                            lhsRef = (Reference)lhs.Evaluate();
                        }
                    }
                    else
                    {
                        iterationEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                        if (_tdzNames != null)
                        {
                            BindingInstantiation(iterationEnv);
                        }
                        _engine.UpdateLexicalEnvironment(iterationEnv);

                        if (!destructuring)
                        {
                            if (lhsName == null)
                            {
                                lhsName = ((Identifier)((VariableDeclaration)_leftNode).Declarations[0].Id).Name;
                            }
                            lhsRef = _engine.ResolveBinding(lhsName);
                        }
                    }

                    if (!destructuring)
                    {
                        // If lhsRef is an abrupt completion, then
                        // Let status be lhsRef.

                        if (lhsKind == LhsKind.LexicalBinding)
                        {
                            lhsRef.InitializeReferencedBinding(nextValue);
                        }
                        else
                        {
                            _engine.PutValue(lhsRef, nextValue);
                        }
                    }
                    else
                    {
                        BindingPatternAssignmentExpression.ProcessPatterns(
                            _engine,
                            _assignmentPattern,
                            nextValue,
                            iterationEnv,
                            checkObjectPatternPropertyReference: _lhsKind != LhsKind.VarBinding);

                        if (lhsKind == LhsKind.Assignment)
                        {
                            // DestructuringAssignmentEvaluation of assignmentPattern using nextValue as the argument.
                        }
                        else if (lhsKind == LhsKind.VarBinding)
                        {
                            // BindingInitialization for lhs passing nextValue and undefined as the arguments.
                        }
                        else
                        {
                            // BindingInitialization for lhs passing nextValue and iterationEnv as arguments
                        }
                    }

                    var result = stmt.Execute();
                    _engine.UpdateLexicalEnvironment(oldEnv);

                    if (!ReferenceEquals(result.Value, null))
                    {
                        v = result.Value;
                    }

                    if (result.Type == CompletionType.Break && (result.Identifier == null || result.Identifier == _statement?.LabelSet?.Name))
                    {
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }

                    if (result.Type != CompletionType.Continue || (result.Identifier != null && result.Identifier != _statement?.LabelSet?.Name))
                    {
                        if (result.Type != CompletionType.Normal)
                        {
                            return(result);
                        }
                    }
                }
            }
            catch
            {
                completionType = CompletionType.Throw;
                throw;
            }
            finally
            {
                if (close)
                {
                    iteratorRecord.Close(completionType);
                }
                _engine.UpdateLexicalEnvironment(oldEnv);
            }
        }
Esempio n. 3
0
 protected void IteratorClose(CompletionType completionType)
 {
     _iterator.Close(completionType);
 }
Esempio n. 4
0
        private static void HandleArrayPattern(Engine engine, ArrayPattern pattern, JsValue argument, LexicalEnvironment environment)
        {
            var             obj             = TypeConverter.ToObject(engine, argument);
            ArrayOperations arrayOperations = null;
            IIterator       iterator        = null;

            if (obj.IsArrayLike)
            {
                arrayOperations = ArrayOperations.For(obj);
            }
            else
            {
                if (!obj.TryGetIterator(engine, out iterator))
                {
                    ExceptionHelper.ThrowTypeError(engine);
                    return;
                }
            }

            var  completionType = CompletionType.Normal;
            var  close          = false;
            var  done           = false;
            uint i = 0;

            try
            {
                for (; i < pattern.Elements.Count; i++)
                {
                    var left = pattern.Elements[(int)i];

                    if (left is null)
                    {
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out _);
                        }
                        else
                        {
                            if (!ConsumeFromIterator(iterator, out _, out done))
                            {
                                break;
                            }
                        }
                        // skip assignment
                        continue;
                    }

                    if (left is Identifier identifier)
                    {
                        JsValue value;
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out value);
                        }
                        else
                        {
                            if (!ConsumeFromIterator(iterator, out value, out done))
                            {
                                break;
                            }
                        }

                        AssignToIdentifier(engine, identifier.Name, value, environment);
                    }
                    else if (left is MemberExpression me)
                    {
                        close = true;
                        var     reference = GetReferenceFromMember(engine, me);
                        JsValue value;
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out value);
                        }
                        else
                        {
                            ConsumeFromIterator(iterator, out value, out done);
                        }

                        AssignToReference(engine, reference, value, environment);
                    }
                    else if (left is BindingPattern bindingPattern)
                    {
                        JsValue value;
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out value);
                        }
                        else
                        {
                            iterator.TryIteratorStep(out var temp);
                            value = temp;
                        }
                        ProcessPatterns(engine, bindingPattern, value, environment);
                    }
                    else if (left is RestElement restElement)
                    {
                        close = true;
                        Reference reference = null;
                        if (restElement.Argument is MemberExpression memberExpression)
                        {
                            reference = GetReferenceFromMember(engine, memberExpression);
                        }

                        ArrayInstance array;
                        if (arrayOperations != null)
                        {
                            var length = arrayOperations.GetLength();
                            array = engine.Array.ConstructFast(length - i);
                            for (uint j = i; j < length; ++j)
                            {
                                arrayOperations.TryGetValue(j, out var indexValue);
                                array.SetIndexValue(j - i, indexValue, updateLength: false);
                            }
                        }
                        else
                        {
                            array = engine.Array.ConstructFast(0);
                            uint index = 0;
                            done = true;
                            do
                            {
                                if (!iterator.TryIteratorStep(out var item))
                                {
                                    done = true;
                                    break;
                                }

                                var value = item.Get(CommonProperties.Value);
                                array.SetIndexValue(index++, value, updateLength: false);
                            } while (true);

                            array.SetLength(index);
                        }

                        if (restElement.Argument is Identifier leftIdentifier)
                        {
                            AssignToIdentifier(engine, leftIdentifier.Name, array, environment);
                        }
                        else if (restElement.Argument is BindingPattern bp)
                        {
                            ProcessPatterns(engine, bp, array, environment);
                        }
                        else
                        {
                            AssignToReference(engine, reference, array, environment);
                        }
                    }
                    else if (left is AssignmentPattern assignmentPattern)
                    {
                        JsValue value;
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out value);
                        }
                        else
                        {
                            ConsumeFromIterator(iterator, out value, out done);
                        }

                        if (value.IsUndefined())
                        {
                            var jintExpression = Build(engine, assignmentPattern.Right);
                            value = jintExpression.GetValue();
                        }

                        if (assignmentPattern.Left is Identifier leftIdentifier)
                        {
                            if (assignmentPattern.Right.IsFunctionWithName())
                            {
                                ((FunctionInstance)value).SetFunctionName(new JsString(leftIdentifier.Name));
                            }

                            AssignToIdentifier(engine, leftIdentifier.Name, value, environment);
                        }
                        else if (assignmentPattern.Left is BindingPattern bp)
                        {
                            ProcessPatterns(engine, bp, value, environment);
                        }
                    }
                    else
                    {
                        ExceptionHelper.ThrowArgumentOutOfRangeException("pattern",
                                                                         "Unable to determine how to handle array pattern element " + left);
                        break;
                    }
                }

                close = true;
            }
            catch
            {
                completionType = CompletionType.Throw;
                throw;
            }
            finally
            {
                if (close && !done)
                {
                    iterator?.Close(completionType);
                }
            }
        }