Skip to content

Commit 2e22853

Browse files
committed
Implement Iterator Helpers
1 parent 5342ebb commit 2e22853

File tree

8 files changed

+494
-20
lines changed

8 files changed

+494
-20
lines changed

Jint.Tests.Test262/Test262Harness.settings.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"SuiteGitSha": "b0f03cb22d8b9233347782d166e7793d4d4c757f",
2+
"SuiteGitSha": "d8e2cb274167073d3a0979085eeec5c1258ab042",
33
//"SuiteDirectory": "//mnt/c/work/test262",
44
"TargetPath": "./Generated",
55
"Namespace": "Jint.Tests.Test262",
@@ -11,7 +11,6 @@
1111
"decorators",
1212
"explicit-resource-management",
1313
"import-defer",
14-
"iterator-helpers",
1514
"iterator-sequencing",
1615
"json-parse-with-source",
1716
"regexp-lookbehind",

Jint/Native/Global/GlobalObject.Properties.cs

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public partial class GlobalObject
2828
private static readonly Key propertyInt16Array = "Int16Array";
2929
private static readonly Key propertyInt32Array = "Int32Array";
3030
private static readonly Key propertyInt8Array = "Int8Array";
31+
private static readonly Key propertyIterator = "Iterator";
3132
//private static readonly Key propertyIntl = "Intl";
3233
private static readonly Key propertyJSON = "JSON";
3334
private static readonly Key propertyMap = "Map";
@@ -105,6 +106,7 @@ protected override void Initialize()
105106
properties.AddDangerous(propertyInt32Array, new LazyPropertyDescriptor<GlobalObject>(this, static global => global._realm.Intrinsics.Int32Array, PropertyFlags));
106107
properties.AddDangerous(propertyInt8Array, new LazyPropertyDescriptor<GlobalObject>(this, static global => global._realm.Intrinsics.Int8Array, PropertyFlags));
107108
// TODO properties.AddDapropertygerous(propertyIntl, new LazyPropertyDescriptor<GlobalObject>(this, static global => global._realm.Intrinsics.Intl, propertyFlags));
109+
properties.AddDangerous(propertyIterator, new LazyPropertyDescriptor<GlobalObject>(this, static global => global._realm.Intrinsics.Iterator, PropertyFlags));
108110
properties.AddDangerous(propertyJSON, new LazyPropertyDescriptor<GlobalObject>(this, static global => global._realm.Intrinsics.Json, PropertyFlags));
109111
properties.AddDangerous(propertyMap, new LazyPropertyDescriptor<GlobalObject>(this, static global => global._realm.Intrinsics.Map, PropertyFlags));
110112
properties.AddDangerous(propertyMath, new LazyPropertyDescriptor<GlobalObject>(this, static global => global._realm.Intrinsics.Math, PropertyFlags));
+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
using Jint.Native.Function;
2+
using Jint.Native.Object;
3+
using Jint.Native.Symbol;
4+
using Jint.Runtime;
5+
using Jint.Runtime.Descriptors;
6+
using Jint.Runtime.Interop;
7+
8+
namespace Jint.Native.Iterator;
9+
10+
internal sealed class IteratorConstructor : Constructor
11+
{
12+
private static readonly JsString _functionName = new("Iterator");
13+
14+
internal IteratorConstructor(
15+
Engine engine,
16+
Realm realm,
17+
FunctionPrototype functionPrototype,
18+
ObjectPrototype objectPrototype)
19+
: base(engine, realm, _functionName)
20+
{
21+
_prototype = functionPrototype;
22+
PrototypeObject = new IteratorPrototype(engine, realm, this);
23+
_length = new PropertyDescriptor(0, PropertyFlag.Configurable);
24+
_prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
25+
}
26+
27+
private IteratorPrototype PrototypeObject { get; }
28+
29+
protected override void Initialize()
30+
{
31+
const PropertyFlag PropertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
32+
const PropertyFlag LengthFlags = PropertyFlag.Configurable;
33+
var properties = new PropertyDictionary(1, checkExistingKeys: false) { ["from"] = new(new PropertyDescriptor(new ClrFunction(Engine, "from", From, 1, LengthFlags), PropertyFlags)), };
34+
SetProperties(properties);
35+
}
36+
37+
public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
38+
{
39+
if (newTarget.IsUndefined() || ReferenceEquals(this, newTarget))
40+
{
41+
ExceptionHelper.ThrowTypeError(_realm);
42+
}
43+
44+
return OrdinaryCreateFromConstructor(
45+
newTarget,
46+
static intrinsics => intrinsics.Iterator.PrototypeObject,
47+
static (Engine engine, Realm realm, object? _) => new JsObject(engine));
48+
}
49+
50+
/// <summary>
51+
/// https://tc39.es/ecma262/#sec-iterator.from
52+
/// </summary>
53+
private JsValue From(JsValue thisObject, JsValue[] arguments)
54+
{
55+
var iteratorRecord = GetIteratorFlattenable(thisObject, StringHandlingType.IterateStringPrimitives);
56+
var hasInstance = _engine.Intrinsics.Iterator.OrdinaryHasInstance(iteratorRecord);
57+
if (hasInstance)
58+
{
59+
return iteratorRecord;
60+
}
61+
62+
var wrapper = new WrapForValidIteratorPrototype(_engine, iteratorRecord);
63+
return wrapper;
64+
}
65+
66+
private IteratorInstance.ObjectIterator GetIteratorFlattenable(JsValue obj, StringHandlingType stringHandling)
67+
{
68+
if (obj is not ObjectInstance)
69+
{
70+
if (stringHandling == StringHandlingType.RejectStrings || obj.IsString())
71+
{
72+
ExceptionHelper.ThrowTypeError(_realm);
73+
}
74+
}
75+
76+
JsValue iterator;
77+
var method = JsValue.GetMethod(_realm, obj, GlobalSymbolRegistry.Iterator);
78+
if (method is null)
79+
{
80+
iterator = obj;
81+
}
82+
else
83+
{
84+
iterator = method.Call(obj);
85+
}
86+
87+
if (iterator is not ObjectInstance objectInstance)
88+
{
89+
ExceptionHelper.ThrowTypeError(_realm);
90+
return null;
91+
}
92+
93+
return new IteratorInstance.ObjectIterator(objectInstance);
94+
}
95+
96+
private sealed class WrapForValidIteratorPrototype : ObjectInstance
97+
{
98+
public WrapForValidIteratorPrototype(
99+
Engine engine,
100+
IteratorInstance.ObjectIterator iterated) : base(engine)
101+
{
102+
Iterated = iterated;
103+
SetPrototypeOf(engine.Intrinsics.IteratorPrototype);
104+
}
105+
106+
public IteratorInstance.ObjectIterator Iterated { get; }
107+
108+
public ObjectInstance Next()
109+
{
110+
var iteratorRecord = Iterated;
111+
iteratorRecord.TryIteratorStep(out var obj);
112+
return obj;
113+
}
114+
115+
public JsValue Return()
116+
{
117+
var iterator = Iterated.GetIterator(_engine.Realm);
118+
var returnMethod = iterator.GetMethod(CommonProperties.Return);
119+
if (returnMethod is null)
120+
{
121+
return CreateIteratorResultObject(Undefined, done: JsBoolean.True);
122+
}
123+
124+
return returnMethod.Call(iterator);
125+
}
126+
127+
/// <summary>
128+
/// https://tc39.es/ecma262/#sec-createiterresultobject
129+
/// </summary>
130+
private IteratorResult CreateIteratorResultObject(JsValue value, JsBoolean done)
131+
{
132+
return IteratorResult.CreateValueIteratorPosition(_engine, value, done);
133+
}
134+
}
135+
136+
private enum StringHandlingType
137+
{
138+
IterateStringPrimitives,
139+
RejectStrings
140+
}
141+
}

0 commit comments

Comments
 (0)