123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- using Jint.Native.Object;
- using Jint.Runtime;
- namespace Jint.Native.Iterator
- {
- /// <summary>
- /// Handles looping of iterator values, sub-classes can use to implement wanted actions.
- /// </summary>
- internal abstract class IteratorProtocol
- {
- private readonly Engine _engine;
- private readonly IteratorInstance _iterator;
- private readonly int _argCount;
- protected IteratorProtocol(
- Engine engine,
- IteratorInstance iterator,
- int argCount)
- {
- _engine = engine;
- _iterator = iterator;
- _argCount = argCount;
- }
- internal bool Execute()
- {
- var args = _engine._jsValueArrayPool.RentArray(_argCount);
- var done = false;
- try
- {
- while (ShouldContinue)
- {
- if (!_iterator.TryIteratorStep(out var item))
- {
- done = true;
- break;
- }
- var currentValue = item.Get(CommonProperties.Value);
- ProcessItem(args, currentValue);
- }
- }
- catch
- {
- IteratorClose(CompletionType.Throw);
- throw;
- }
- finally
- {
- _engine._jsValueArrayPool.ReturnArray(args);
- }
- IterationEnd();
- return done;
- }
- protected void IteratorClose(CompletionType completionType)
- {
- _iterator.Close(completionType);
- }
- protected virtual bool ShouldContinue => true;
- protected virtual void IterationEnd()
- {
- }
- protected abstract void ProcessItem(JsValue[] arguments, JsValue currentValue);
- internal static void AddEntriesFromIterable(ObjectInstance target, IteratorInstance iterable, object adder)
- {
- var callable = adder as ICallable;
- if (callable is null)
- {
- ExceptionHelper.ThrowTypeError(target.Engine.Realm, "adder must be callable");
- }
- 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;
- var oi = temp as ObjectInstance;
- if (oi is null)
- {
- ExceptionHelper.ThrowTypeError(target.Engine.Realm, "iterator's value must be an object");
- }
- 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);
- }
- }
- }
- }
|