Explorar o código

Create base constructs for Intl support (#1492)

Marko Lahma %!s(int64=2) %!d(string=hai) anos
pai
achega
e11fabeaad
Modificáronse 31 ficheiros con 1212 adicións e 25 borrados
  1. 8 8
      Jint/Native/BigInt/BigIntPrototype.cs
  2. 2 1
      Jint/Native/Global/GlobalObject.cs
  3. 33 0
      Jint/Native/Intl/CollatorConstructor.cs
  4. 39 0
      Jint/Native/Intl/CollatorPrototype.cs
  5. 55 0
      Jint/Native/Intl/DateTimeFormatConstructor.cs
  6. 39 0
      Jint/Native/Intl/DateTimeFormatPrototype.cs
  7. 33 0
      Jint/Native/Intl/DisplayNamesConstructor.cs
  8. 39 0
      Jint/Native/Intl/DisplayNamesPrototype.cs
  9. 55 0
      Jint/Native/Intl/IntlInstance.cs
  10. 33 0
      Jint/Native/Intl/ListFormatConstructor.cs
  11. 39 0
      Jint/Native/Intl/ListFormatPrototype.cs
  12. 33 0
      Jint/Native/Intl/LocaleConstructor.cs
  13. 39 0
      Jint/Native/Intl/LocalePrototype.cs
  14. 366 0
      Jint/Native/Intl/NumberFormatConstructor.cs
  15. 40 0
      Jint/Native/Intl/NumberFormatPrototype.cs
  16. 55 0
      Jint/Native/Intl/PluralRulesConstructor.cs
  17. 40 0
      Jint/Native/Intl/PluralRulesPrototype.cs
  18. 55 0
      Jint/Native/Intl/RelativeTimeFormatConstructor.cs
  19. 40 0
      Jint/Native/Intl/RelativeTimeFormatPrototype.cs
  20. 33 0
      Jint/Native/Intl/SegmenterConstructor.cs
  21. 40 0
      Jint/Native/Intl/SegmenterPrototype.cs
  22. 30 1
      Jint/Native/JsString.cs
  23. 7 3
      Jint/Native/Object/ObjectInstance.cs
  24. 5 5
      Jint/Native/Promise/PromiseConstructor.cs
  25. 1 1
      Jint/Runtime/CallStack/JintCallStack.cs
  26. 1 1
      Jint/Runtime/Debugger/DebugScopes.cs
  27. 1 1
      Jint/Runtime/Environments/ExecutionContext.cs
  28. 1 2
      Jint/Runtime/IScriptOrModule.Extensions.cs
  29. 48 0
      Jint/Runtime/Intrinsics.Intl.cs
  30. 1 1
      Jint/Runtime/Intrinsics.cs
  31. 1 1
      Jint/Runtime/Modules/BuilderModuleRecord.cs

+ 8 - 8
Jint/Native/BigInt/BigIntPrototype.cs

@@ -45,17 +45,17 @@ internal sealed class BigIntPrototype : Prototype
     }
 
     /// <summary>
-    /// https://tc39.es/ecma262/#sec-bigint.prototype.tolocalestring
+    /// https://tc39.es/ecma402/#sup-bigint.prototype.tolocalestring
     /// </summary>
     private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
     {
-        if (!thisObject.IsBigInt() && thisObject is not BigIntInstance)
-        {
-            ExceptionHelper.ThrowTypeError(_realm);
-        }
+        var locales = arguments.At(0);
+        var options = arguments.At(1);
 
-        var m = TypeConverter.ToBigInt(thisObject);
-        return m.ToString("R");
+        var x = ThisBigIntValue(thisObject);
+        //var numberFormat = (NumberFormat) Construct(_realm.Intrinsics.NumberFormat, new[] {  locales, options });
+        // numberFormat.FormatNumeric(x);
+        return x._value.ToString("R");
     }
 
     /// <summary>
@@ -144,7 +144,7 @@ internal sealed class BigIntPrototype : Prototype
                 return bigIntInstance.BigIntData;
             default:
                 ExceptionHelper.ThrowTypeError(_realm);
-                return JsBigInt.One;
+                return default;
         }
     }
 }

+ 2 - 1
Jint/Native/Global/GlobalObject.cs

@@ -29,7 +29,7 @@ namespace Jint.Native.Global
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
 
-            var properties = new PropertyDictionary(55, checkExistingKeys: false)
+            var properties = new PropertyDictionary(56, checkExistingKeys: false)
             {
                 ["AggregateError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.AggregateError, propertyFlags),
                 ["Array"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.Array, propertyFlags),
@@ -50,6 +50,7 @@ namespace Jint.Native.Global
                 ["Int16Array"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.Int16Array, propertyFlags),
                 ["Int32Array"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.Int32Array, propertyFlags),
                 ["Int8Array"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.Int8Array, propertyFlags),
+                // TODO ["Intl"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.Intl, propertyFlags),
                 ["JSON"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.Json, propertyFlags),
                 ["Map"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.Map, propertyFlags),
                 ["Math"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state!)._realm.Intrinsics.Math, propertyFlags),

+ 33 - 0
Jint/Native/Intl/CollatorConstructor.cs

@@ -0,0 +1,33 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-the-intl-collator-constructor
+/// </summary>
+internal sealed class CollatorConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("Collator");
+
+    public CollatorConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new CollatorPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public CollatorPrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        throw new NotImplementedException();
+    }
+}

+ 39 - 0
Jint/Native/Intl/CollatorPrototype.cs

@@ -0,0 +1,39 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-the-intl-collator-prototype-object
+/// </summary>
+internal sealed class CollatorPrototype : Prototype
+{
+    private readonly CollatorConstructor _constructor;
+
+    public CollatorPrototype(Engine engine,
+        Realm realm,
+        CollatorConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.Collator", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 55 - 0
Jint/Native/Intl/DateTimeFormatConstructor.cs

@@ -0,0 +1,55 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-intl-datetimeformat-constructor
+/// </summary>
+internal sealed class DateTimeFormatConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("DateTimeFormat");
+
+    public DateTimeFormatConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new DateTimeFormatPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public DateTimeFormatPrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var locales = arguments.At(0);
+        var options = arguments.At(1);
+
+        if (newTarget.IsUndefined())
+        {
+            newTarget = this;
+        }
+
+        var dateTimeFormat = OrdinaryCreateFromConstructor<JsObject, object>(
+            newTarget,
+            static intrinsics => intrinsics.DateTimeFormat.PrototypeObject,
+            static (engine, _, _) => new JsObject(engine));
+
+        InitializeDateTimeFormat(dateTimeFormat, locales, options);
+        return dateTimeFormat;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-initializedatetimeformat
+    /// </summary>
+    private void InitializeDateTimeFormat(JsObject dateTimeFormat, JsValue locales, JsValue options)
+    {
+        // TODO
+    }
+}

+ 39 - 0
Jint/Native/Intl/DateTimeFormatPrototype.cs

@@ -0,0 +1,39 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-intl-datetimeformat-prototype-object
+/// </summary>
+internal sealed class DateTimeFormatPrototype : Prototype
+{
+    private readonly DateTimeFormatConstructor _constructor;
+
+    public DateTimeFormatPrototype(Engine engine,
+        Realm realm,
+        DateTimeFormatConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.DateTimeFormat", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 33 - 0
Jint/Native/Intl/DisplayNamesConstructor.cs

@@ -0,0 +1,33 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-intl-displaynames-constructor
+/// </summary>
+internal sealed class DisplayNamesConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("DisplayNames");
+
+    public DisplayNamesConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new DisplayNamesPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public DisplayNamesPrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        throw new NotImplementedException();
+    }
+}

+ 39 - 0
Jint/Native/Intl/DisplayNamesPrototype.cs

@@ -0,0 +1,39 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-intl-displaynames-prototype-object
+/// </summary>
+internal sealed class DisplayNamesPrototype : Prototype
+{
+    private readonly DisplayNamesConstructor _constructor;
+
+    public DisplayNamesPrototype(Engine engine,
+        Realm realm,
+        DisplayNamesConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.DisplayNames", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 55 - 0
Jint/Native/Intl/IntlInstance.cs

@@ -0,0 +1,55 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+using Jint.Runtime.Interop;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#intl-object
+/// </summary>
+internal sealed class IntlInstance : ObjectInstance
+{
+    private readonly Realm _realm;
+
+    internal IntlInstance(
+        Engine engine,
+        Realm realm,
+        ObjectPrototype objectPrototype) : base(engine)
+    {
+        _realm = realm;
+        _prototype = objectPrototype;
+    }
+
+    protected override void Initialize()
+    {
+        // TODO check length
+        var properties = new PropertyDictionary(10, checkExistingKeys: false)
+        {
+            ["Collator"] = new(_realm.Intrinsics.Collator, false, false, true),
+            ["DateTimeFormat"] = new(_realm.Intrinsics.DateTimeFormat, false, false, true),
+            ["DisplayNames"] = new(_realm.Intrinsics.DisplayNames, false, false, true),
+            ["ListFormat"] = new(_realm.Intrinsics.ListFormat, false, false, true),
+            ["Locale"] = new(_realm.Intrinsics.Locale, false, false, true),
+            ["NumberFormat"] = new(_realm.Intrinsics.NumberFormat, false, false, true),
+            ["PluralRules"] = new(_realm.Intrinsics.PluralRules, false, false, true),
+            ["RelativeTimeFormat"] = new(_realm.Intrinsics.RelativeTimeFormat, false, false, true),
+            ["Segmenter"] = new(_realm.Intrinsics.Segmenter, false, false, true),
+            ["getCanonicalLocales "] = new(new ClrFunctionInstance(Engine, "getCanonicalLocales ", GetCanonicalLocales , 1, PropertyFlag.Configurable), true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+
+    private JsValue GetCanonicalLocales(JsValue thisObject, JsValue[] arguments)
+    {
+        return new JsArray(_engine);
+    }
+}

+ 33 - 0
Jint/Native/Intl/ListFormatConstructor.cs

@@ -0,0 +1,33 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-intl-listformat-constructor
+/// </summary>
+internal sealed class ListFormatConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("ListFormat");
+
+    public ListFormatConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new ListFormatPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public ListFormatPrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        throw new NotImplementedException();
+    }
+}

+ 39 - 0
Jint/Native/Intl/ListFormatPrototype.cs

@@ -0,0 +1,39 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-intl-listformat-prototype-object
+/// </summary>
+internal sealed class ListFormatPrototype : Prototype
+{
+    private readonly ListFormatConstructor _constructor;
+
+    public ListFormatPrototype(Engine engine,
+        Realm realm,
+        ListFormatConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.ListFormat", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 33 - 0
Jint/Native/Intl/LocaleConstructor.cs

@@ -0,0 +1,33 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-intl-locale-constructor
+/// </summary>
+internal sealed class LocaleConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("Locale");
+
+    public LocaleConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new LocalePrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public LocalePrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        throw new NotImplementedException();
+    }
+}

+ 39 - 0
Jint/Native/Intl/LocalePrototype.cs

@@ -0,0 +1,39 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-intl-locale-prototype-object
+/// </summary>
+internal sealed class LocalePrototype : Prototype
+{
+    private readonly LocaleConstructor _constructor;
+
+    public LocalePrototype(Engine engine,
+        Realm realm,
+        LocaleConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.Locale", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 366 - 0
Jint/Native/Intl/NumberFormatConstructor.cs

@@ -0,0 +1,366 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-intl-numberformat-constructor
+/// </summary>
+internal sealed class NumberFormatConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("NumberFormat");
+
+    public NumberFormatConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new NumberFormatPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public NumberFormatPrototype PrototypeObject { get; }
+
+    public object LocaleData { get; private set; } = null!;
+    public object AvailableLocales { get; private set; } = null!;
+    public object RelevantExtensionKeys { get; private set; } = null!;
+
+
+    protected override void Initialize()
+    {
+        LocaleData = new object();
+        AvailableLocales = new object();
+        RelevantExtensionKeys = new object();
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-intl.numberformat
+    /// </summary>
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var locales = arguments.At(0);
+        var options = arguments.At(1);
+
+        if (newTarget.IsUndefined())
+        {
+            newTarget = this;
+        }
+
+        var numberFormat = OrdinaryCreateFromConstructor<JsObject, object>(
+            newTarget,
+            static intrinsics => intrinsics.NumberFormat.PrototypeObject,
+            static (engine, _, _) => new JsObject(engine));
+
+        InitializeNumberFormat(numberFormat, locales, options);
+        return numberFormat;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-initializenumberformat
+    /// </summary>
+    private JsObject InitializeNumberFormat(JsObject numberFormat, JsValue locales, JsValue opts)
+    {
+        var requestedLocales = CanonicalizeLocaleList(locales);
+        var options = CoerceOptionsToObject(opts);
+        var opt = new JsObject(_engine);
+
+        var matcher = GetOption(options, "localeMatcher", OptionType.String, new JsValue[] { "lookup", "best fit" }, "best fit");
+        opt["localeMatcher"] = matcher;
+
+        var numberingSystem = GetOption(options, "numberingSystem", OptionType.String, System.Array.Empty<JsValue>(), Undefined);
+        if (!numberingSystem.IsUndefined())
+        {
+            // If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
+        }
+
+        opt["nu"] = numberingSystem;
+        var localeData = LocaleData;
+        var r = ResolveLocale(_engine.Realm.Intrinsics.NumberFormat.AvailableLocales, requestedLocales, opt, _engine.Realm.Intrinsics.NumberFormat.RelevantExtensionKeys, localeData);
+        numberFormat["Locale"] = r["locale"];
+        numberFormat["DataLocale"] = r["dataLocale"];
+        numberFormat["NumberingSystem"] = r["nu"];
+        SetNumberFormatUnitOptions(numberFormat, options);
+
+        int mnfdDefault;
+        int mxfdDefault;
+        var style = numberFormat["Style"];
+        if (style == "currency")
+        {
+            var currency = numberFormat["Currency"];
+            var cDigits = CurrencyDigits(currency);
+            mnfdDefault = cDigits;
+            mxfdDefault = cDigits;
+        }
+        else
+        {
+            mnfdDefault = 0;
+            mxfdDefault = style == "percent" ? 0 : 3;
+        }
+
+        var notation = GetOption(options, "notation", OptionType.String, new JsValue[] { "standard", "scientific", "engineering", "compact" }, "standard");
+        numberFormat["Notation"] = notation;
+        SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation.ToString());
+
+        var compactDisplay = GetOption(options, "compactDisplay", OptionType.String, new JsValue[] { "short", "long" }, "short");
+        if (notation == "compact")
+        {
+            numberFormat["CompactDisplay"] = compactDisplay;
+        }
+
+        var useGrouping = GetOption(options, "useGrouping", OptionType.Boolean, System.Array.Empty<JsValue>(), JsBoolean.True);
+        numberFormat["UseGrouping"] = useGrouping;
+        var signDisplay = GetOption(options, "signDisplay", OptionType.String, new JsValue[] { "auto", "never", "always", "exceptZero" }, "auto");
+        numberFormat["SignDisplay"] = signDisplay;
+
+        return numberFormat;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-resolvelocale
+    /// </summary>
+    private JsObject ResolveLocale(object availableLocales, JsArray requestedLocales, JsObject options, object relevantExtensionKeys, object localeData)
+    {
+        // TODO
+        var result = new JsObject(_engine);
+        return result;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-setnfdigitoptions
+    /// </summary>
+    private static void SetNumberFormatDigitOptions(JsObject numberFormat, ObjectInstance options, int mnfdDefault, int mxfdDefault, string notation)
+    {
+        // TODO
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-currencydigits
+    /// </summary>
+    private static int CurrencyDigits(JsValue currency)
+    {
+        // TODO
+        return 2;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-setnumberformatunitoptions
+    /// </summary>
+    private void SetNumberFormatUnitOptions(JsObject intlObj, JsValue options)
+    {
+        var style = GetOption(options, "style", OptionType.String, new JsValue[] { "decimal", "percent", "currency", "unit" }, "decimal");
+        intlObj["Style"] = style;
+        var currency = GetOption(options, "currency", OptionType.String, System.Array.Empty<JsValue>(), Undefined);
+        if (currency.IsUndefined())
+        {
+            if (style == "currency")
+            {
+                ExceptionHelper.ThrowTypeError(_realm, "No currency found when style currency requested");
+            }
+        }
+        else if (!IsWellFormedCurrencyCode(currency))
+        {
+            ExceptionHelper.ThrowRangeError(_realm, "Invalid currency code");
+        }
+
+        var currencyDisplay = GetOption(options, "currencyDisplay", OptionType.String, new JsValue[] { "code", "symbol", "narrowSymbol", "name" }, "symbol");
+        var currencySign = GetOption(options, "currencySign", OptionType.String, new JsValue[] { "standard", "accounting" }, "standard");
+        var unit = GetOption(options, "unit", OptionType.String, System.Array.Empty<JsValue>(), Undefined);
+
+        if (unit.IsUndefined())
+        {
+            if (style == "unit")
+            {
+                ExceptionHelper.ThrowTypeError(_realm, "No unit found when style unit requested");
+            }
+        }
+        else if (!IsWellFormedUnitIdentifier(unit))
+        {
+            ExceptionHelper.ThrowRangeError(_realm, "Invalid unit");
+        }
+
+        var unitDisplay = GetOption(options, "unitDisplay", OptionType.String, new JsValue[] { "short", "narrow", "long" }, "short");
+        if (style == "currency")
+        {
+            intlObj["Currency"] = currency.ToString().ToUpperInvariant();
+            intlObj["CurrencyDisplay"] = currencyDisplay;
+            intlObj["CurrencySign"] = currencySign;
+        }
+
+        if (style == "unit")
+        {
+            intlObj["Unit"] = unit;
+            intlObj["UnitDisplay"] = unitDisplay;
+        }
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-iswellformedunitidentifier
+    /// </summary>
+    private bool IsWellFormedUnitIdentifier(JsValue unitIdentifier)
+    {
+        var value = unitIdentifier.ToString();
+        if (IsSanctionedSingleUnitIdentifier(value))
+        {
+            return true;
+        }
+
+        var i = value.IndexOf("-per-");
+        if (i == -1 || value.IndexOf("-per-", i + 1) != -1)
+        {
+            return false;
+        }
+
+        var numerator = value.Substring(0, i);
+        var denominator = value.Substring(i + 5);
+        if (IsSanctionedSingleUnitIdentifier(numerator) && IsSanctionedSingleUnitIdentifier(denominator))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    private static readonly HashSet<string> _sanctionedSingleUnitIdentifiers = new()
+    {
+        "acre",
+        "bit",
+        "byte",
+        "celsius",
+        "centimeter",
+        "day",
+        "degree",
+        "fahrenheit",
+        "fluid-ounce",
+        "foot",
+        "gallon",
+        "gigabit",
+        "gigabyte",
+        "gram",
+        "hectare",
+        "hour",
+        "inch",
+        "kilobit",
+        "kilobyte",
+        "kilogram",
+        "kilometer",
+        "liter",
+        "megabit",
+        "megabyte",
+        "meter",
+        "microsecond",
+        "mile",
+        "mile-scandinavian",
+        "milliliter",
+        "millimeter",
+        "millisecond",
+        "minute",
+        "month",
+        "nanosecond",
+        "ounce",
+        "percent",
+        "petabyte",
+        "pound",
+        "second",
+        "stone",
+        "terabit",
+        "terabyte",
+        "week",
+        "yard",
+        "year",
+    };
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-issanctionedsingleunitidentifier
+    /// </summary>
+    private static bool IsSanctionedSingleUnitIdentifier(string unitIdentifier) => _sanctionedSingleUnitIdentifiers.Contains(unitIdentifier);
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-iswellformedcurrencycode
+    /// </summary>
+    private static bool IsWellFormedCurrencyCode(JsValue currency)
+    {
+        var value = currency.ToString();
+        return value.Length == 3 && char.IsLetter(value[0]) && char.IsLetter(value[1]) && char.IsLetter(value[2]);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-coerceoptionstoobject
+    /// </summary>
+    private ObjectInstance CoerceOptionsToObject(JsValue options)
+    {
+        if (options.IsUndefined())
+        {
+            return OrdinaryObjectCreate(_engine, null);
+        }
+
+        return TypeConverter.ToObject(_realm, options);
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-canonicalizelocalelist
+    /// </summary>
+    private JsArray CanonicalizeLocaleList(JsValue locales)
+    {
+        return new JsArray(_engine);
+        // TODO
+    }
+
+    private enum OptionType
+    {
+        Boolean,
+        Number,
+        String
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-getoption
+    /// </summary>
+    private JsValue GetOption<T>(JsValue options, string property, OptionType type, T[] values, T defaultValue) where T : JsValue
+    {
+        var value = options.Get(property);
+        if (value.IsUndefined())
+        {
+            if (defaultValue == "required")
+            {
+                ExceptionHelper.ThrowRangeError(_realm, "Required value missing");
+            }
+
+            return defaultValue;
+        }
+
+        switch (type)
+        {
+            case OptionType.Boolean:
+                value = TypeConverter.ToBoolean(value);
+                break;
+            case OptionType.Number:
+                {
+                    var number = TypeConverter.ToNumber(value);
+                    if (double.IsNaN(number))
+                    {
+                        ExceptionHelper.ThrowRangeError(_realm, "Invalid number value");
+                    }
+                    value = number;
+                    break;
+                }
+            case OptionType.String:
+                value = TypeConverter.ToString(value);
+                break;
+            default:
+                ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(type), "Unknown type");
+                break;
+        }
+
+        if (values.Length > 0 && System.Array.IndexOf(values, value) == -1)
+        {
+            ExceptionHelper.ThrowRangeError(_realm, "Value not part of list");
+        }
+
+        return value;
+    }
+}

+ 40 - 0
Jint/Native/Intl/NumberFormatPrototype.cs

@@ -0,0 +1,40 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-intl-numberformat-prototype-object
+/// </summary>
+internal sealed class NumberFormatPrototype : Prototype
+{
+    private readonly NumberFormatConstructor _constructor;
+
+    public NumberFormatPrototype(
+        Engine engine,
+        Realm realm,
+        NumberFormatConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.NumberFormat", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 55 - 0
Jint/Native/Intl/PluralRulesConstructor.cs

@@ -0,0 +1,55 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-intl-pluralrules-constructor
+/// </summary>
+internal sealed class PluralRulesConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("PluralRules");
+
+    public PluralRulesConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new PluralRulesPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public PluralRulesPrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var locales = arguments.At(0);
+        var options = arguments.At(1);
+
+        if (newTarget.IsUndefined())
+        {
+            newTarget = this;
+        }
+
+        var pluralRules = OrdinaryCreateFromConstructor<JsObject, object>(
+            newTarget,
+            static intrinsics => intrinsics.PluralRules.PrototypeObject,
+            static (engine, _, _) => new JsObject(engine));
+
+        InitializePluralRules(pluralRules, locales, options);
+        return pluralRules;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-initializepluralrules
+    /// </summary>
+    private void InitializePluralRules(JsObject pluralRules, JsValue locales, JsValue options)
+    {
+        // TODO
+    }
+}

+ 40 - 0
Jint/Native/Intl/PluralRulesPrototype.cs

@@ -0,0 +1,40 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-intl-pluralrules-prototype-object
+/// </summary>
+internal sealed class PluralRulesPrototype : Prototype
+{
+    private readonly PluralRulesConstructor _constructor;
+
+    public PluralRulesPrototype(
+        Engine engine,
+        Realm realm,
+        PluralRulesConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.PluralRules", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 55 - 0
Jint/Native/Intl/RelativeTimeFormatConstructor.cs

@@ -0,0 +1,55 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-intl-relativetimeformat-constructor
+/// </summary>
+internal sealed class RelativeTimeFormatConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("RelativeTimeFormat");
+
+    public RelativeTimeFormatConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new RelativeTimeFormatPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public RelativeTimeFormatPrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var locales = arguments.At(0);
+        var options = arguments.At(1);
+
+        if (newTarget.IsUndefined())
+        {
+            newTarget = this;
+        }
+
+        var relativeTimeFormat = OrdinaryCreateFromConstructor<JsObject, object>(
+            newTarget,
+            static intrinsics => intrinsics.RelativeTimeFormat.PrototypeObject,
+            static (engine, _, _) => new JsObject(engine));
+
+        InitializeRelativeTimeFormat(relativeTimeFormat, locales, options);
+        return relativeTimeFormat;
+    }
+
+    /// <summary>
+    /// https://tc39.es/ecma402/#sec-InitializeRelativeTimeFormat
+    /// </summary>
+    private void InitializeRelativeTimeFormat(JsObject relativeTimeFormat, JsValue locales, JsValue options)
+    {
+        // TODO
+    }
+}

+ 40 - 0
Jint/Native/Intl/RelativeTimeFormatPrototype.cs

@@ -0,0 +1,40 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-intl-relativetimeformat-prototype-object
+/// </summary>
+internal sealed class RelativeTimeFormatPrototype : Prototype
+{
+    private readonly RelativeTimeFormatConstructor _constructor;
+
+    public RelativeTimeFormatPrototype(
+        Engine engine,
+        Realm realm,
+        RelativeTimeFormatConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.RelativeTimeFormat", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 33 - 0
Jint/Native/Intl/SegmenterConstructor.cs

@@ -0,0 +1,33 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-intl-segmenter-constructor
+/// </summary>
+internal sealed class SegmenterConstructor : Constructor
+{
+    private static readonly JsString _functionName = new("Segmenter");
+
+    public SegmenterConstructor(
+        Engine engine,
+        Realm realm,
+        FunctionPrototype functionPrototype,
+        ObjectPrototype objectPrototype) : base(engine, realm, _functionName)
+    {
+        _prototype = functionPrototype;
+        PrototypeObject = new SegmenterPrototype(engine, realm, this, objectPrototype);
+        _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    public SegmenterPrototype PrototypeObject { get; }
+
+    public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        throw new NotImplementedException();
+    }
+}

+ 40 - 0
Jint/Native/Intl/SegmenterPrototype.cs

@@ -0,0 +1,40 @@
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Intl;
+
+/// <summary>
+/// https://tc39.es/ecma402/#sec-properties-of-intl-segmenter-prototype-object
+/// </summary>
+internal sealed class SegmenterPrototype : Prototype
+{
+    private readonly SegmenterConstructor _constructor;
+
+    public SegmenterPrototype(
+        Engine engine,
+        Realm realm,
+        SegmenterConstructor constructor,
+        ObjectPrototype objectPrototype) : base(engine, realm)
+    {
+        _prototype = objectPrototype;
+        _constructor = constructor;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(2, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
+        };
+        SetProperties(properties);
+
+        var symbols = new SymbolDictionary(1)
+        {
+            [GlobalSymbolRegistry.ToStringTag] = new("Intl.Segmenter", PropertyFlag.Configurable)
+        };
+        SetSymbols(symbols);
+    }
+}

+ 30 - 1
Jint/Native/JsString.cs

@@ -3,7 +3,7 @@ using Jint.Runtime;
 
 namespace Jint.Native;
 
-public class JsString : JsValue, IEquatable<JsString>
+public class JsString : JsValue, IEquatable<JsString>, IEquatable<string>
 {
     private const int AsciiMax = 126;
     private static readonly JsString[] _charToJsValue;
@@ -255,6 +255,11 @@ public class JsString : JsValue, IEquatable<JsString>
         return Equals(obj as JsString);
     }
 
+    public virtual bool Equals(string? s)
+    {
+        return s != null && ToString() == s;
+    }
+
     public virtual bool Equals(JsString? other)
     {
         if (other is null)
@@ -348,6 +353,30 @@ public class JsString : JsValue, IEquatable<JsString>
 
         public override int Length => _stringBuilder?.Length ?? _value?.Length ?? 0;
 
+        public override bool Equals(string? s)
+        {
+            if (s is null || Length != s.Length)
+            {
+                return false;
+            }
+
+            // we cannot use StringBuilder.Equals as it also checks Capacity on full framework / pre .NET Core 3
+            if (_stringBuilder != null)
+            {
+                for (var i = 0; i < _stringBuilder.Length; ++i)
+                {
+                    if (_stringBuilder[i] != s[i])
+                    {
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+
+            return _value == s;
+        }
+
         public override bool Equals(JsString? other)
         {
             if (other is ConcatenatedString cs)

+ 7 - 3
Jint/Native/Object/ObjectInstance.cs

@@ -82,7 +82,11 @@ namespace Jint.Native.Object
             get => _class;
         }
 
-        public JsValue this[JsValue property] => Get(property);
+        public JsValue this[JsValue property]
+        {
+            get => Get(property);
+            set => Set(property, value);
+        }
 
         /// <summary>
         /// https://tc39.es/ecma262/#sec-construct
@@ -637,7 +641,7 @@ namespace Jint.Native.Object
             }
 
             var parent = GetPrototypeOf();
-            if (parent != null)
+            if (parent is not null)
             {
                 return parent.HasProperty(key);
             }
@@ -1262,7 +1266,7 @@ namespace Jint.Native.Object
         /// <summary>
         /// https://tc39.es/ecma262/#sec-ordinaryobjectcreate
         /// </summary>
-        internal static ObjectInstance OrdinaryObjectCreate(Engine engine, ObjectInstance? proto)
+        internal static JsObject OrdinaryObjectCreate(Engine engine, ObjectInstance? proto)
         {
             var prototype = new JsObject(engine)
             {

+ 5 - 5
Jint/Native/Promise/PromiseConstructor.cs

@@ -224,7 +224,7 @@ namespace Jint.Native.Promise
                 // Note that "Undefined" is not null, thus the logic is sound, even though awkward
                 // also note that it is important to check if we are done iterating.
                 // if "then" method is sync then it will be resolved BEFORE the next iteration cycle
-                if (results.TrueForAll(static x => x != null) && doneIterating)
+                if (results.TrueForAll(static x => x is not null) && doneIterating)
                 {
                     var array = _realm.Intrinsics.Array.ConstructFast(results);
                     resolve.Call(Undefined, new JsValue[] { array });
@@ -320,7 +320,7 @@ namespace Jint.Native.Promise
                 // Note that "Undefined" is not null, thus the logic is sound, even though awkward
                 // also note that it is important to check if we are done iterating.
                 // if "then" method is sync then it will be resolved BEFORE the next iteration cycle
-                if (results.TrueForAll(static x => x != null) && doneIterating)
+                if (results.TrueForAll(static x => x is not null) && doneIterating)
                 {
                     var array = _realm.Intrinsics.Array.ConstructFast(results);
                     resolve.Call(Undefined, new JsValue[] { array });
@@ -441,7 +441,7 @@ namespace Jint.Native.Promise
                 // also note that it is important to check if we are done iterating.
                 // if "then" method is sync then it will be resolved BEFORE the next iteration cycle
 
-                if (errors.TrueForAll(static x => x != null) && doneIterating)
+                if (errors.TrueForAll(static x => x is not null) && doneIterating)
                 {
                     var array = _realm.Intrinsics.Array.ConstructFast(errors);
 
@@ -636,8 +636,8 @@ namespace Jint.Native.Promise
                 // 4. If promiseCapability.[[Reject]] is not undefined, throw a TypeError exception.
                 // 5. Set promiseCapability.[[Resolve]] to resolve.
                 // 6. Set promiseCapability.[[Reject]] to reject.
-                if (resolveArg != null && resolveArg != Undefined ||
-                    rejectArg != null && rejectArg != Undefined)
+                if (resolveArg is not null && resolveArg != Undefined ||
+                    rejectArg is not null && rejectArg != Undefined)
                 {
                     ExceptionHelper.ThrowTypeError(engine.Realm, "executor was already called with not undefined args");
                 }

+ 1 - 1
Jint/Runtime/CallStack/JintCallStack.cs

@@ -25,7 +25,7 @@ namespace Jint.Runtime.CallStack
             var lex = LexicalEnvironment;
             while (true)
             {
-                if (lex != null)
+                if (lex is not null)
                 {
                     if (lex.HasThisBinding())
                     {

+ 1 - 1
Jint/Runtime/Debugger/DebugScopes.cs

@@ -18,7 +18,7 @@ namespace Jint.Runtime.Debugger
         private void Populate(EnvironmentRecord? environment)
         {
             bool inLocalScope = true;
-            while (environment != null)
+            while (environment is not null)
             {
                 var record = environment;
                 switch (record)

+ 1 - 1
Jint/Runtime/Environments/ExecutionContext.cs

@@ -54,7 +54,7 @@ internal readonly struct ExecutionContext
         var lex = LexicalEnvironment;
         while (true)
         {
-            if (lex != null)
+            if (lex is not null)
             {
                 if (lex.HasThisBinding())
                 {

+ 1 - 2
Jint/Runtime/IScriptOrModule.Extensions.cs

@@ -7,8 +7,7 @@ internal static class ScriptOrModuleExtensions
 {
     public static ModuleRecord AsModule(this IScriptOrModule? scriptOrModule, Engine engine, Location location)
     {
-        var module = scriptOrModule as ModuleRecord;
-        if (module == null)
+        if (scriptOrModule is not ModuleRecord module)
         {
             ExceptionHelper.ThrowSyntaxError(engine.Realm, "Cannot use import/export statements outside a module", location);
             return default!;

+ 48 - 0
Jint/Runtime/Intrinsics.Intl.cs

@@ -0,0 +1,48 @@
+using Jint.Native.Intl;
+
+namespace Jint.Runtime
+{
+    public sealed partial class Intrinsics
+    {
+        private IntlInstance? _intl;
+        private CollatorConstructor? _collator;
+        private DateTimeFormatConstructor? _dateTimeFormat;
+        private DisplayNamesConstructor? _displayNames;
+        private ListFormatConstructor? _listFormat;
+        private LocaleConstructor? _locale;
+        private NumberFormatConstructor? _numberFormat;
+        private PluralRulesConstructor? _pluralRules;
+        private RelativeTimeFormatConstructor? _relativeTimeFormat;
+        private SegmenterConstructor? _segmenter;
+
+        internal IntlInstance Intl =>
+            _intl ??= new IntlInstance(_engine, _realm, Object.PrototypeObject);
+
+        internal CollatorConstructor Collator =>
+            _collator ??= new CollatorConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+
+        internal DateTimeFormatConstructor DateTimeFormat =>
+            _dateTimeFormat ??= new DateTimeFormatConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+
+        internal DisplayNamesConstructor DisplayNames =>
+            _displayNames ??= new DisplayNamesConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+
+        internal ListFormatConstructor ListFormat =>
+            _listFormat ??= new ListFormatConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+
+        internal LocaleConstructor Locale =>
+            _locale ??= new LocaleConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+
+        internal NumberFormatConstructor NumberFormat =>
+            _numberFormat ??= new NumberFormatConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+
+        internal PluralRulesConstructor PluralRules =>
+            _pluralRules ??= new PluralRulesConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+
+        internal RelativeTimeFormatConstructor RelativeTimeFormat =>
+            _relativeTimeFormat ??= new RelativeTimeFormatConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+
+        internal SegmenterConstructor Segmenter =>
+            _segmenter ??= new SegmenterConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
+    }
+}

+ 1 - 1
Jint/Runtime/Intrinsics.cs

@@ -31,7 +31,7 @@ using Jint.Native.WeakSet;
 
 namespace Jint.Runtime
 {
-    public sealed class Intrinsics
+    public sealed partial class Intrinsics
     {
         private static readonly JsString _errorFunctionName = new("Error");
         private static readonly JsString _evalErrorFunctionName = new("EvalError");

+ 1 - 1
Jint/Runtime/Modules/BuilderModuleRecord.cs

@@ -17,7 +17,7 @@ internal sealed class BuilderModuleRecord : SourceTextModuleRecord
 
     internal void BindExportedValue(string name, JsValue value)
     {
-        if (_environment != null)
+        if (_environment is not null)
         {
             ExceptionHelper.ThrowInvalidOperationException("Cannot bind exported values after the environment has been initialized");
         }