Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Promise.withResolvers and update test suite #1650

Merged
merged 1 commit into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Jint.Tests.PublicInterface/ShadowRealmTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Jint.Native;
using Jint.Native.Object;

namespace Jint.Tests.PublicInterface;
Expand Down
3 changes: 2 additions & 1 deletion Jint.Tests.Test262/Test262Harness.settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"SuiteGitSha": "9437cab774ab2f22c5cb971b11b8512eca705721",
"SuiteGitSha": "6396ebde0316639292530460d1ef961fd9bbe0d4",
//"SuiteDirectory": "//mnt/c/work/test262",
"TargetPath": "./Generated",
"Namespace": "Jint.Tests.Test262",
Expand Down Expand Up @@ -46,6 +46,7 @@
// RegExp handling problems
"built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js",
"language/literals/regexp/u-case-mapping.js",
"built-ins/RegExp/lookahead-quantifier-match-groups.js",

// requires investigation how to process complex function name evaluation for property
"built-ins/Function/prototype/toString/method-computed-property-name.js",
Expand Down
31 changes: 21 additions & 10 deletions Jint/Native/Promise/PromiseConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ internal sealed class PromiseConstructor : Constructor
{
private static readonly JsString _functionName = new JsString("Promise");

internal PromisePrototype PrototypeObject { get; private set; }

internal PromiseConstructor(
Engine engine,
Realm realm,
Expand All @@ -36,18 +34,21 @@ internal PromiseConstructor(
_prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
}

internal PromisePrototype PrototypeObject { get; }

protected override void Initialize()
{
const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
const PropertyFlag lengthFlags = PropertyFlag.Configurable;
const PropertyFlag PropertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
const PropertyFlag LengthFlags = PropertyFlag.Configurable;
var properties = new PropertyDictionary(6, checkExistingKeys: false)
{
["resolve"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "resolve", Resolve, 1, lengthFlags), propertyFlags)),
["reject"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "reject", Reject, 1, lengthFlags), propertyFlags)),
["all"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "all", All, 1, lengthFlags), propertyFlags)),
["allSettled"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "allSettled", AllSettled, 1, lengthFlags), propertyFlags)),
["any"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "any", Any, 1, lengthFlags), propertyFlags)),
["race"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "race", Race, 1, lengthFlags), propertyFlags)),
["all"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "all", All, 1, LengthFlags), PropertyFlags)),
["allSettled"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "allSettled", AllSettled, 1, LengthFlags), PropertyFlags)),
["any"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "any", Any, 1, LengthFlags), PropertyFlags)),
["race"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "race", Race, 1, LengthFlags), PropertyFlags)),
["reject"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "reject", Reject, 1, LengthFlags), PropertyFlags)),
["resolve"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "resolve", Resolve, 1, LengthFlags), PropertyFlags)),
["withResolvers"] = new(new PropertyDescriptor(new ClrFunctionInstance(Engine, "withResolvers", WithResolvers , 0, LengthFlags), PropertyFlags)),
};
SetProperties(properties);

Expand Down Expand Up @@ -113,6 +114,16 @@ internal JsValue Resolve(JsValue thisObject, JsValue[] arguments)
return PromiseResolve(thisObject, x);
}

private JsValue WithResolvers(JsValue thisObject, JsValue[] arguments)
{
var promiseCapability = NewPromiseCapability(_engine, thisObject);
var obj = OrdinaryObjectCreate(_engine, _engine.Realm.Intrinsics.Object.PrototypeObject);
obj.CreateDataPropertyOrThrow("promise", promiseCapability.PromiseInstance);
obj.CreateDataPropertyOrThrow("resolve", promiseCapability.ResolveObj);
obj.CreateDataPropertyOrThrow("reject", promiseCapability.RejectObj);
return obj;
}

/// <summary>
/// https://tc39.es/ecma262/#sec-promise-resolve
/// </summary>
Expand Down
1 change: 0 additions & 1 deletion Jint/Native/Proxy/JsProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Interop;

namespace Jint.Native.Proxy
{
Expand Down
2 changes: 2 additions & 0 deletions Jint/Native/RegExp/JsRegExp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public string Flags
public bool FullUnicode { get; private set; }
public bool UnicodeSets { get; private set; }

internal bool HasDefaultRegExpExec => Properties == null && Prototype is RegExpPrototype { HasDefaultExec: true };

public override PropertyDescriptor GetOwnProperty(JsValue property)
{
if (property == PropertyLastIndex)
Expand Down
25 changes: 2 additions & 23 deletions Jint/Native/RegExp/RegExpExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Jint.Native.Object;
namespace Jint.Native.RegExp;

namespace Jint.Native.RegExp
internal static class RegExpExtensions
{
internal static class RegExpExtensions
{
internal static bool TryGetDefaultRegExpExec(this ObjectInstance? o, [NotNullWhen(true)] out Func<JsValue, JsValue[], JsValue>? exec)
{
if (o is RegExpPrototype prototype)
{
return prototype.TryGetDefaultExec(prototype, out exec);
}

if (o is JsRegExp instance)
{
exec = default;
return instance.Properties == null
&& TryGetDefaultRegExpExec(instance.Prototype, out exec);
}

exec = default;
return false;
}
}
}
27 changes: 8 additions & 19 deletions Jint/Native/RegExp/RegExpPrototype.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
using System.Text.RegularExpressions;
using Jint.Collections;
using Jint.Native.Number;
using Jint.Native.Object;
Expand Down Expand Up @@ -158,7 +157,7 @@ private JsValue Replace(JsValue thisObject, JsValue[] arguments)
if (!fullUnicode
&& !mayHaveNamedCaptures
&& !TypeConverter.ToBoolean(rx.Get(PropertySticky))
&& rx is JsRegExp rei && rei.TryGetDefaultRegExpExec(out _))
&& rx is JsRegExp rei && rei.HasDefaultRegExpExec)
{
var count = global ? int.MaxValue : 1;

Expand Down Expand Up @@ -464,7 +463,7 @@ private JsValue Split(JsValue thisObject, JsValue[] arguments)
return a;
}

if (!unicodeMatching && rx is JsRegExp R && R.TryGetDefaultRegExpExec(out _))
if (!unicodeMatching && rx is JsRegExp R && R.HasDefaultRegExpExec)
{
// we can take faster path

Expand Down Expand Up @@ -690,7 +689,7 @@ private JsValue Match(JsValue thisObject, JsValue[] arguments)

if (!fullUnicode
&& rx is JsRegExp rei
&& rei.TryGetDefaultRegExpExec(out _))
&& rei.HasDefaultRegExpExec)
{
// fast path
var a = _realm.Intrinsics.Array.ArrayCreate(0);
Expand Down Expand Up @@ -812,8 +811,9 @@ private static ulong AdvanceStringIndex(string s, ulong index, bool unicode)

internal static JsValue RegExpExec(ObjectInstance r, string s)
{
var exec = r.Get(PropertyExec);
if (exec is ICallable callable)
var ri = r as JsRegExp;

if ((ri is null || !ri.HasDefaultRegExpExec) && r.Get(PropertyExec) is ICallable callable)
{
var result = callable.Call(r, new JsValue[] { s });
if (!result.IsNull() && !result.IsObject())
Expand All @@ -824,7 +824,6 @@ internal static JsValue RegExpExec(ObjectInstance r, string s)
return result;
}

var ri = r as JsRegExp;
if (ri is null)
{
ExceptionHelper.ThrowTypeError(r.Engine.Realm);
Expand All @@ -833,17 +832,7 @@ internal static JsValue RegExpExec(ObjectInstance r, string s)
return RegExpBuiltinExec(ri, s);
}

internal bool TryGetDefaultExec(ObjectInstance o, [NotNullWhen((true))] out Func<JsValue, JsValue[], JsValue>? exec)
{
if (o.Get(PropertyExec) is ClrFunctionInstance functionInstance && functionInstance._func == _defaultExec)
{
exec = _defaultExec;
return true;
}

exec = default;
return false;
}
internal bool HasDefaultExec => Get(PropertyExec) is ClrFunctionInstance functionInstance && functionInstance._func == _defaultExec;

/// <summary>
/// https://tc39.es/ecma262/#sec-regexpbuiltinexec
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ Following features are supported in version 3.x.
#### ECMAScript Stage 3 (no version yet)

- ✔ Array Grouping - `Object.groupBy` and `Map.groupBy`
- ✔ Promise.withResolvers
- ✔ ShadowRealm

#### Other
Expand Down