summaryrefslogtreecommitdiffstats
path: root/js/src/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin')
-rw-r--r--js/src/builtin/.eslintrc.js8
-rw-r--r--js/src/builtin/DataViewObject.cpp141
-rw-r--r--js/src/builtin/DataViewObject.h43
-rw-r--r--js/src/builtin/ModuleObject.cpp163
-rw-r--r--js/src/builtin/ModuleObject.h31
-rw-r--r--js/src/builtin/ReflectParse.cpp3
-rw-r--r--js/src/builtin/String.cpp9
-rw-r--r--js/src/builtin/TestingFunctions.cpp146
-rw-r--r--js/src/builtin/intl/NumberFormat.js91
-rw-r--r--js/src/builtin/intl/PluralRules.js42
-rwxr-xr-xjs/src/builtin/intl/make_intl_data.py8
-rw-r--r--js/src/builtin/temporal/PlainDate.cpp3
-rw-r--r--js/src/builtin/temporal/PlainDateTime.cpp3
-rw-r--r--js/src/builtin/temporal/PlainMonthDay.cpp3
-rw-r--r--js/src/builtin/temporal/PlainTime.cpp3
-rw-r--r--js/src/builtin/temporal/PlainYearMonth.cpp3
-rw-r--r--js/src/builtin/temporal/ZonedDateTime.cpp3
17 files changed, 409 insertions, 294 deletions
diff --git a/js/src/builtin/.eslintrc.js b/js/src/builtin/.eslintrc.js
index 89beca7d4c..76aad2f6fd 100644
--- a/js/src/builtin/.eslintrc.js
+++ b/js/src/builtin/.eslintrc.js
@@ -121,6 +121,14 @@ module.exports = {
message: "'const' declarations are disallowed to avoid TDZ checks, use 'var' instead",
},
],
+ // Method signatures are important in builtins so disable unused argument errors.
+ "no-unused-vars": [
+ "error",
+ {
+ args: "none",
+ vars: "local",
+ },
+ ],
},
globals: {
diff --git a/js/src/builtin/DataViewObject.cpp b/js/src/builtin/DataViewObject.cpp
index 1f7be86a70..425fdce51d 100644
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -65,150 +65,27 @@ DataViewObject* DataViewObject::create(
}
ResizableDataViewObject* ResizableDataViewObject::create(
- JSContext* cx, size_t byteOffset, size_t byteLength, bool autoLength,
+ JSContext* cx, size_t byteOffset, size_t byteLength, AutoLength autoLength,
Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, HandleObject proto) {
MOZ_ASSERT(arrayBuffer->isResizable());
MOZ_ASSERT(!arrayBuffer->isDetached());
- MOZ_ASSERT(!autoLength || byteLength == 0,
+ MOZ_ASSERT(autoLength == AutoLength::No || byteLength == 0,
"byte length is zero for 'auto' length views");
auto* obj = NewObjectWithClassProto<ResizableDataViewObject>(cx, proto);
- if (!obj || !obj->init(cx, arrayBuffer, byteOffset, byteLength,
- /* bytesPerElement = */ 1)) {
+ if (!obj || !obj->initResizable(cx, arrayBuffer, byteOffset, byteLength,
+ /* bytesPerElement = */ 1, autoLength)) {
return nullptr;
}
- obj->setFixedSlot(AUTO_LENGTH_SLOT, BooleanValue(autoLength));
-
return obj;
}
-/**
- * GetViewByteLength ( viewRecord )
- *
- * GetViewByteLength can be rewritten into the following spec steps when
- * inlining the calls to MakeDataViewWithBufferWitnessRecord and
- * IsViewOutOfBounds.
- *
- * 1. Let buffer be view.[[ViewedArrayBuffer]].
- * 2. If IsDetachedBuffer(buffer) is true, then
- * a. Return out-of-bounds.
- * 3. If IsFixedLengthArrayBuffer(buffer) is true,
- * a. Return view.[[ByteLength]].
- * 4. Let bufferByteLength be ArrayBufferByteLength(buffer, order).
- * 5. Let byteOffsetStart be view.[[ByteOffset]].
- * 6. If byteOffsetStart > bufferByteLength, then
- * a. Return out-of-bounds.
- * 7. If view.[[ByteLength]] is auto, then
- * a. Return bufferByteLength - byteOffsetStart.
- * 8. Let viewByteLength be view.[[ByteLength]].
- * 9. Let byteOffsetEnd be byteOffsetStart + viewByteLength.
- * 10. If byteOffsetEnd > bufferByteLength, then
- * a. Return out-of-bounds.
- * 11. Return viewByteLength.
- *
- * The additional call to IsFixedLengthArrayBuffer is an optimization to skip
- * unnecessary validation which doesn't apply for fixed length data-views.
- *
- * https://tc39.es/ecma262/#sec-getviewbytelength
- * https://tc39.es/ecma262/#sec-makedataviewwithbufferwitnessrecord
- * https://tc39.es/ecma262/#sec-isviewoutofbounds
- */
-mozilla::Maybe<size_t> DataViewObject::byteLength() {
- if (MOZ_UNLIKELY(hasDetachedBuffer())) {
- return mozilla::Nothing{};
- }
-
- if (MOZ_LIKELY(is<FixedLengthDataViewObject>())) {
- size_t viewByteLength = rawByteLength();
- return mozilla::Some(viewByteLength);
- }
-
- auto* buffer = bufferEither();
- MOZ_ASSERT(buffer->isResizable());
-
- size_t bufferByteLength = buffer->byteLength();
- size_t byteOffsetStart = ArrayBufferViewObject::byteOffset();
- if (byteOffsetStart > bufferByteLength) {
- return mozilla::Nothing{};
- }
-
- if (as<ResizableDataViewObject>().isAutoLength()) {
- return mozilla::Some(bufferByteLength - byteOffsetStart);
- }
-
- size_t viewByteLength = rawByteLength();
- size_t byteOffsetEnd = byteOffsetStart + viewByteLength;
- if (byteOffsetEnd > bufferByteLength) {
- return mozilla::Nothing{};
- }
- return mozilla::Some(viewByteLength);
-}
-
-/**
- * IsViewOutOfBounds ( viewRecord )
- *
- * IsViewOutOfBounds can be rewritten into the following spec steps when
- * inlining the call to MakeDataViewWithBufferWitnessRecord.
- *
- * 1. Let buffer be obj.[[ViewedArrayBuffer]].
- * 2. If IsDetachedBuffer(buffer) is true, then
- * a. Return true.
- * 3. If IsFixedLengthArrayBuffer(buffer) is true, then
- * a. Return false.
- * 4. Let byteLength be ArrayBufferByteLength(buffer, order).
- * 5. Let byteOffsetStart be view.[[ByteOffset]].
- * 6. If byteOffsetStart > bufferByteLength, then
- * a. Return true.
- * 7. If view.[[ByteLength]] is auto, then
- * a. Return false.
- * 8. Let byteOffsetEnd be byteOffsetStart + view.[[ByteLength]].
- * 9. If byteOffsetEnd > bufferByteLength, then
- * a. Return true.
- * 10. Return false.
- *
- * The additional call to IsFixedLengthArrayBuffer is an optimization to skip
- * unnecessary validation which doesn't apply for fixed length data-views.
- *
- * https://tc39.es/ecma262/#sec-makedataviewwithbufferwitnessrecord
- * https://tc39.es/ecma262/#sec-isviewoutofbounds
- */
-mozilla::Maybe<size_t> DataViewObject::byteOffset() {
- if (MOZ_UNLIKELY(hasDetachedBuffer())) {
- return mozilla::Nothing{};
- }
-
- size_t byteOffsetStart = ArrayBufferViewObject::byteOffset();
-
- if (MOZ_LIKELY(is<FixedLengthDataViewObject>())) {
- return mozilla::Some(byteOffsetStart);
- }
-
- auto* buffer = bufferEither();
- MOZ_ASSERT(buffer->isResizable());
-
- size_t bufferByteLength = buffer->byteLength();
- if (byteOffsetStart > bufferByteLength) {
- return mozilla::Nothing{};
- }
-
- if (as<ResizableDataViewObject>().isAutoLength()) {
- return mozilla::Some(byteOffsetStart);
- }
-
- size_t viewByteLength = rawByteLength();
- size_t byteOffsetEnd = byteOffsetStart + viewByteLength;
- if (byteOffsetEnd > bufferByteLength) {
- return mozilla::Nothing{};
- }
- return mozilla::Some(byteOffsetStart);
-}
-
// ES2017 draft rev 931261ecef9b047b14daacf82884134da48dfe0f
// 24.3.2.1 DataView (extracted part of the main algorithm)
bool DataViewObject::getAndCheckConstructorArgs(
JSContext* cx, HandleObject bufobj, const CallArgs& args,
- size_t* byteOffsetPtr, size_t* byteLengthPtr, bool* autoLengthPtr) {
+ size_t* byteOffsetPtr, size_t* byteLengthPtr, AutoLength* autoLengthPtr) {
// Step 3.
if (!bufobj->is<ArrayBufferObjectMaybeShared>()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
@@ -243,10 +120,10 @@ bool DataViewObject::getAndCheckConstructorArgs(
MOZ_ASSERT(offset <= ArrayBufferObject::ByteLengthLimit);
uint64_t viewByteLength = 0;
- bool autoLength = false;
+ auto autoLength = AutoLength::No;
if (!args.hasDefined(2)) {
if (buffer->isResizable()) {
- autoLength = true;
+ autoLength = AutoLength::Yes;
} else {
// Step 8.a
viewByteLength = bufferByteLength - offset;
@@ -305,7 +182,7 @@ bool DataViewObject::constructSameCompartment(JSContext* cx,
size_t byteOffset = 0;
size_t byteLength = 0;
- bool autoLength = false;
+ auto autoLength = AutoLength::No;
if (!getAndCheckConstructorArgs(cx, bufobj, args, &byteOffset, &byteLength,
&autoLength)) {
return false;
@@ -365,7 +242,7 @@ bool DataViewObject::constructWrapped(JSContext* cx, HandleObject bufobj,
// NB: This entails the IsArrayBuffer check
size_t byteOffset = 0;
size_t byteLength = 0;
- bool autoLength = false;
+ auto autoLength = AutoLength::No;
if (!getAndCheckConstructorArgs(cx, unwrapped, args, &byteOffset, &byteLength,
&autoLength)) {
return false;
diff --git a/js/src/builtin/DataViewObject.h b/js/src/builtin/DataViewObject.h
index a17b3e1174..db134a5696 100644
--- a/js/src/builtin/DataViewObject.h
+++ b/js/src/builtin/DataViewObject.h
@@ -48,7 +48,7 @@ class DataViewObject : public ArrayBufferViewObject {
const CallArgs& args,
size_t* byteOffsetPtr,
size_t* byteLengthPtr,
- bool* autoLengthPtr);
+ AutoLength* autoLengthPtr);
static bool constructSameCompartment(JSContext* cx, HandleObject bufobj,
const CallArgs& args);
static bool constructWrapped(JSContext* cx, HandleObject bufobj,
@@ -58,16 +58,16 @@ class DataViewObject : public ArrayBufferViewObject {
JSContext* cx, size_t byteOffset, size_t byteLength,
Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, HandleObject proto);
- protected:
- size_t rawByteLength() const {
- return size_t(getFixedSlot(LENGTH_SLOT).toPrivate());
- }
-
public:
static const JSClass protoClass_;
- mozilla::Maybe<size_t> byteLength();
- mozilla::Maybe<size_t> byteOffset();
+ /**
+ * Return the current byteLength, or |Nothing| if the DataView is detached or
+ * out-of-bounds.
+ */
+ mozilla::Maybe<size_t> byteLength() {
+ return ArrayBufferViewObject::length();
+ }
template <typename NativeType>
static bool offsetIsInBounds(uint64_t offset, size_t byteLength) {
@@ -173,19 +173,11 @@ class FixedLengthDataViewObject : public DataViewObject {
public:
static const JSClass class_;
- size_t byteOffset() const { return ArrayBufferViewObject::byteOffset(); }
-
- size_t byteLength() const { return rawByteLength(); }
-
- bool offsetIsInBounds(uint32_t byteSize, uint64_t offset) const {
- return DataViewObject::offsetIsInBounds(byteSize, offset, byteLength());
+ size_t byteOffset() const {
+ return ArrayBufferViewObject::byteOffsetSlotValue();
}
- template <typename NativeType>
- NativeType read(uint64_t offset, bool isLittleEndian) {
- return DataViewObject::read<NativeType>(offset, byteLength(),
- isLittleEndian);
- }
+ size_t byteLength() const { return ArrayBufferViewObject::lengthSlotValue(); }
};
/**
@@ -195,19 +187,14 @@ class ResizableDataViewObject : public DataViewObject {
friend class DataViewObject;
static ResizableDataViewObject* create(
- JSContext* cx, size_t byteOffset, size_t byteLength, bool autoLength,
- Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, HandleObject proto);
+ JSContext* cx, size_t byteOffset, size_t byteLength,
+ AutoLength autoLength, Handle<ArrayBufferObjectMaybeShared*> arrayBuffer,
+ HandleObject proto);
public:
- static const uint8_t AUTO_LENGTH_SLOT = DataViewObject::RESERVED_SLOTS;
-
- static const uint8_t RESERVED_SLOTS = DataViewObject::RESERVED_SLOTS + 1;
+ static const uint8_t RESERVED_SLOTS = RESIZABLE_RESERVED_SLOTS;
static const JSClass class_;
-
- bool isAutoLength() const {
- return getFixedSlot(AUTO_LENGTH_SLOT).toBoolean();
- }
};
// For structured cloning.
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 0be9aec17b..b9db9bf02d 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -20,7 +20,7 @@
#include "gc/Tracer.h"
#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin, JS::LimitedColumnNumberOneOrigin
#include "js/friend/ErrorMessages.h" // JSMSG_*
-#include "js/Modules.h" // JS::GetModulePrivate, JS::ModuleDynamicImportHook
+#include "js/Modules.h" // JS::GetModulePrivate, JS::ModuleDynamicImportHook, JS::ModuleType
#include "vm/EqualityOperations.h" // js::SameValue
#include "vm/Interpreter.h" // Execute, Lambda, ReportRuntimeLexicalError
#include "vm/ModuleBuilder.h" // js::ModuleBuilder
@@ -31,6 +31,7 @@
#include "builtin/HandlerFunction-inl.h" // js::ExtraValueFromHandler, js::NewHandler{,WithExtraValue}, js::TargetFromHandler
#include "gc/GCContext-inl.h"
+#include "vm/EnvironmentObject-inl.h" // EnvironmentObject::setAliasedBinding
#include "vm/JSObject-inl.h"
#include "vm/JSScript-inl.h"
#include "vm/List-inl.h"
@@ -184,8 +185,8 @@ ResolvedBindingObject* ResolvedBindingObject::create(
DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ModuleRequestObject, specifier,
SpecifierSlot)
-ArrayObject* ModuleRequestObject::assertions() const {
- JSObject* obj = getReservedSlot(AssertionSlot).toObjectOrNull();
+ArrayObject* ModuleRequestObject::attributes() const {
+ JSObject* obj = getReservedSlot(AttributesSlot).toObjectOrNull();
if (!obj) {
return nullptr;
}
@@ -193,6 +194,52 @@ ArrayObject* ModuleRequestObject::assertions() const {
return &obj->as<ArrayObject>();
}
+bool ModuleRequestObject::hasAttributes() const {
+ return !getReservedSlot(ModuleRequestObject::AttributesSlot)
+ .isNullOrUndefined();
+}
+
+/* static */
+bool ModuleRequestObject::getModuleType(
+ JSContext* cx, const Handle<ModuleRequestObject*> moduleRequest,
+ JS::ModuleType& moduleType) {
+ if (!moduleRequest->hasAttributes()) {
+ moduleType = JS::ModuleType::JavaScript;
+ return true;
+ }
+
+ Rooted<ArrayObject*> attributesArray(cx, moduleRequest->attributes());
+ RootedObject attributeObject(cx);
+ RootedId typeId(cx, NameToId(cx->names().type));
+ RootedValue value(cx);
+
+ uint32_t numberOfAttributes = attributesArray->length();
+ for (uint32_t i = 0; i < numberOfAttributes; i++) {
+ attributeObject = &attributesArray->getDenseElement(i).toObject();
+
+ if (!GetProperty(cx, attributeObject, attributeObject, typeId, &value)) {
+ continue;
+ }
+
+ int32_t isJsonString;
+ if (!js::CompareStrings(cx, cx->names().json, value.toString(),
+ &isJsonString)) {
+ return false;
+ }
+
+ if (isJsonString == 0) {
+ moduleType = JS::ModuleType::JSON;
+ return true;
+ }
+
+ moduleType = JS::ModuleType::Unknown;
+ return true;
+ }
+
+ moduleType = JS::ModuleType::JavaScript;
+ return true;
+}
+
/* static */
bool ModuleRequestObject::isInstance(HandleValue value) {
return value.isObject() && value.toObject().is<ModuleRequestObject>();
@@ -201,7 +248,7 @@ bool ModuleRequestObject::isInstance(HandleValue value) {
/* static */
ModuleRequestObject* ModuleRequestObject::create(
JSContext* cx, Handle<JSAtom*> specifier,
- Handle<ArrayObject*> maybeAssertions) {
+ Handle<ArrayObject*> maybeAttributes) {
ModuleRequestObject* self =
NewObjectWithGivenProto<ModuleRequestObject>(cx, nullptr);
if (!self) {
@@ -209,7 +256,7 @@ ModuleRequestObject* ModuleRequestObject::create(
}
self->initReservedSlot(SpecifierSlot, StringOrNullValue(specifier));
- self->initReservedSlot(AssertionSlot, ObjectOrNullValue(maybeAssertions));
+ self->initReservedSlot(AttributesSlot, ObjectOrNullValue(maybeAttributes));
return self;
}
@@ -618,6 +665,21 @@ void ModuleNamespaceObject::ProxyHandler::finalize(JS::GCContext* gcx,
}
///////////////////////////////////////////////////////////////////////////
+// SyntheticModuleFields
+
+// The fields of a synthetic module record, as described in:
+// https://tc39.es/proposal-json-modules/#sec-synthetic-module-records
+class js::SyntheticModuleFields {
+ public:
+ ExportNameVector exportNames;
+
+ public:
+ void trace(JSTracer* trc);
+};
+
+void SyntheticModuleFields::trace(JSTracer* trc) { exportNames.trace(trc); }
+
+///////////////////////////////////////////////////////////////////////////
// CyclicModuleFields
// The fields of a cyclic module record, as described in:
@@ -857,6 +919,10 @@ Span<const ExportEntry> ModuleObject::starExportEntries() const {
return cyclicModuleFields()->starExportEntries();
}
+const ExportNameVector& ModuleObject::syntheticExportNames() const {
+ return syntheticModuleFields()->exportNames;
+}
+
void ModuleObject::initFunctionDeclarations(
UniquePtr<FunctionDeclarationVector> decls) {
cyclicModuleFields()->functionDeclarations = std::move(decls);
@@ -883,12 +949,39 @@ ModuleObject* ModuleObject::create(JSContext* cx) {
}
/* static */
+ModuleObject* ModuleObject::createSynthetic(
+ JSContext* cx, MutableHandle<ExportNameVector> exportNames) {
+ Rooted<UniquePtr<SyntheticModuleFields>> syntheticFields(cx);
+ syntheticFields = cx->make_unique<SyntheticModuleFields>();
+ if (!syntheticFields) {
+ return nullptr;
+ }
+
+ Rooted<ModuleObject*> self(
+ cx, NewObjectWithGivenProto<ModuleObject>(cx, nullptr));
+ if (!self) {
+ return nullptr;
+ }
+
+ InitReservedSlot(self, SyntheticModuleFieldsSlot, syntheticFields.release(),
+ MemoryUse::ModuleSyntheticFields);
+
+ self->syntheticModuleFields()->exportNames = std::move(exportNames.get());
+
+ return self;
+}
+
+/* static */
void ModuleObject::finalize(JS::GCContext* gcx, JSObject* obj) {
ModuleObject* self = &obj->as<ModuleObject>();
if (self->hasCyclicModuleFields()) {
gcx->delete_(obj, self->cyclicModuleFields(),
MemoryUse::ModuleCyclicFields);
}
+ if (self->hasSyntheticModuleFields()) {
+ gcx->delete_(obj, self->syntheticModuleFields(),
+ MemoryUse::ModuleSyntheticFields);
+ }
}
ModuleEnvironmentObject& ModuleObject::initialEnvironment() const {
@@ -960,6 +1053,7 @@ void ModuleObject::setAsyncEvaluating() {
void ModuleObject::initScriptSlots(HandleScript script) {
MOZ_ASSERT(script);
MOZ_ASSERT(script->sourceObject());
+ MOZ_ASSERT(script->filename());
initReservedSlot(ScriptSlot, PrivateGCThingValue(script));
cyclicModuleFields()->scriptSourceObject = script->sourceObject();
}
@@ -1021,10 +1115,12 @@ static inline void AssertValidModuleStatus(ModuleStatus status) {
}
ModuleStatus ModuleObject::status() const {
- // TODO: When implementing synthetic module records it may be convenient to
- // make this method always return a ModuleStatus::Evaluated for such a module
- // so we can assert a module's status without checking which kind it is, even
- // though synthetic modules don't have this field according to the spec.
+ // Always return `ModuleStatus::Evaluated` so we can assert a module's status
+ // without checking which kind it is, even though synthetic modules don't have
+ // this field according to the spec.
+ if (hasSyntheticModuleFields()) {
+ return ModuleStatus::Evaluated;
+ }
ModuleStatus status = cyclicModuleFields()->status;
AssertValidModuleStatus(status);
@@ -1161,6 +1257,22 @@ ModuleObject* ModuleObject::getCycleRoot() const {
return cyclicModuleFields()->cycleRoot;
}
+bool ModuleObject::hasSyntheticModuleFields() const {
+ bool result = !getReservedSlot(SyntheticModuleFieldsSlot).isUndefined();
+ MOZ_ASSERT_IF(result, !hasCyclicModuleFields());
+ return result;
+}
+
+SyntheticModuleFields* ModuleObject::syntheticModuleFields() {
+ MOZ_ASSERT(!hasCyclicModuleFields());
+ void* ptr = getReservedSlot(SyntheticModuleFieldsSlot).toPrivate();
+ MOZ_ASSERT(ptr);
+ return static_cast<SyntheticModuleFields*>(ptr);
+}
+const SyntheticModuleFields* ModuleObject::syntheticModuleFields() const {
+ return const_cast<ModuleObject*>(this)->syntheticModuleFields();
+}
+
bool ModuleObject::hasTopLevelCapability() const {
return cyclicModuleFields()->topLevelCapability;
}
@@ -1206,6 +1318,9 @@ void ModuleObject::trace(JSTracer* trc, JSObject* obj) {
if (module.hasCyclicModuleFields()) {
module.cyclicModuleFields()->trace(trc);
}
+ if (module.hasSyntheticModuleFields()) {
+ module.syntheticModuleFields()->trace(trc);
+ }
}
/* static */
@@ -1328,6 +1443,27 @@ bool ModuleObject::createEnvironment(JSContext* cx,
return true;
}
+/*static*/
+bool ModuleObject::createSyntheticEnvironment(JSContext* cx,
+ Handle<ModuleObject*> self,
+ Handle<GCVector<Value>> values) {
+ Rooted<ModuleEnvironmentObject*> env(
+ cx, ModuleEnvironmentObject::createSynthetic(cx, self));
+ if (!env) {
+ return false;
+ }
+
+ MOZ_ASSERT(env->shape()->propMapLength() == values.length());
+
+ for (uint32_t i = 0; i < values.length(); i++) {
+ env->setAliasedBinding(env->firstSyntheticValueSlot() + i, values[i]);
+ }
+
+ self->setInitialEnvironment(env);
+
+ return true;
+}
+
///////////////////////////////////////////////////////////////////////////
// ModuleBuilder
@@ -2542,10 +2678,11 @@ static bool OnResolvedDynamicModule(JSContext* cx, unsigned argc, Value* vp) {
return RejectPromiseWithPendingError(cx, promise);
}
- MOZ_ASSERT(module->getCycleRoot()
- ->topLevelCapability()
- ->as<PromiseObject>()
- .state() == JS::PromiseState::Fulfilled);
+ MOZ_ASSERT_IF(module->hasCyclicModuleFields(),
+ module->getCycleRoot()
+ ->topLevelCapability()
+ ->as<PromiseObject>()
+ .state() == JS::PromiseState::Fulfilled);
RootedObject ns(cx, GetOrCreateModuleNamespace(cx, module));
if (!ns) {
diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
index 015cb42a5f..d39d65b18c 100644
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -43,6 +43,7 @@ namespace js {
class ArrayObject;
class CyclicModuleFields;
+class SyntheticModuleFields;
class ListObject;
class ModuleEnvironmentObject;
class ModuleObject;
@@ -51,16 +52,20 @@ class ScriptSourceObject;
class ModuleRequestObject : public NativeObject {
public:
- enum { SpecifierSlot = 0, AssertionSlot, SlotCount };
+ enum { SpecifierSlot = 0, AttributesSlot, SlotCount };
static const JSClass class_;
static bool isInstance(HandleValue value);
[[nodiscard]] static ModuleRequestObject* create(
JSContext* cx, Handle<JSAtom*> specifier,
- Handle<ArrayObject*> maybeAssertions);
+ Handle<ArrayObject*> maybeAttributes);
JSAtom* specifier() const;
- ArrayObject* assertions() const;
+ ArrayObject* attributes() const;
+ bool hasAttributes() const;
+ static bool getModuleType(JSContext* cx,
+ const Handle<ModuleRequestObject*> moduleRequest,
+ JS::ModuleType& moduleType);
};
using ModuleRequestVector =
@@ -309,6 +314,10 @@ constexpr uint32_t ASYNC_EVALUATING_POST_ORDER_INIT = 1;
// Value that the field is set to after being cleared.
constexpr uint32_t ASYNC_EVALUATING_POST_ORDER_CLEARED = 0;
+// Currently, the ModuleObject class is used to represent both the Source Text
+// Module Record and the Synthetic Module Record. Ideally, this is something
+// that should be refactored to follow the same hierarchy as in the spec.
+// TODO: See Bug 1880519.
class ModuleObject : public NativeObject {
public:
// Module fields including those for AbstractModuleRecords described by:
@@ -318,6 +327,8 @@ class ModuleObject : public NativeObject {
EnvironmentSlot,
NamespaceSlot,
CyclicModuleFieldsSlot,
+ // `SyntheticModuleFields` if a synthetic module. Otherwise `undefined`.
+ SyntheticModuleFieldsSlot,
SlotCount
};
@@ -327,6 +338,9 @@ class ModuleObject : public NativeObject {
static ModuleObject* create(JSContext* cx);
+ static ModuleObject* createSynthetic(
+ JSContext* cx, MutableHandle<ExportNameVector> exportNames);
+
// Initialize the slots on this object that are dependent on the script.
void initScriptSlots(HandleScript script);
@@ -364,6 +378,8 @@ class ModuleObject : public NativeObject {
mozilla::Span<const ExportEntry> localExportEntries() const;
mozilla::Span<const ExportEntry> indirectExportEntries() const;
mozilla::Span<const ExportEntry> starExportEntries() const;
+ const ExportNameVector& syntheticExportNames() const;
+
IndirectBindingMap& importBindings();
void setStatus(ModuleStatus newStatus);
@@ -390,6 +406,8 @@ class ModuleObject : public NativeObject {
void clearAsyncEvaluatingPostOrder();
void setCycleRoot(ModuleObject* cycleRoot);
ModuleObject* getCycleRoot() const;
+ bool hasCyclicModuleFields() const;
+ bool hasSyntheticModuleFields() const;
static void onTopLevelEvaluationFinished(ModuleObject* module);
@@ -413,6 +431,9 @@ class ModuleObject : public NativeObject {
MutableHandle<UniquePtr<ExportNameVector>> exports);
static bool createEnvironment(JSContext* cx, Handle<ModuleObject*> self);
+ static bool createSyntheticEnvironment(JSContext* cx,
+ Handle<ModuleObject*> self,
+ Handle<GCVector<Value>> values);
void initAsyncSlots(JSContext* cx, bool hasTopLevelAwait,
Handle<ListObject*> asyncParentModules);
@@ -423,9 +444,11 @@ class ModuleObject : public NativeObject {
static void trace(JSTracer* trc, JSObject* obj);
static void finalize(JS::GCContext* gcx, JSObject* obj);
- bool hasCyclicModuleFields() const;
CyclicModuleFields* cyclicModuleFields();
const CyclicModuleFields* cyclicModuleFields() const;
+
+ SyntheticModuleFields* syntheticModuleFields();
+ const SyntheticModuleFields* syntheticModuleFields() const;
};
JSObject* GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
index 62eac477ad..dde953143e 100644
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -2885,7 +2885,8 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
}
case ParseNodeKind::DotExpr:
- case ParseNodeKind::OptionalDotExpr: {
+ case ParseNodeKind::OptionalDotExpr:
+ case ParseNodeKind::ArgumentsLength: {
PropertyAccessBase* prop = &pn->as<PropertyAccessBase>();
MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos));
diff --git a/js/src/builtin/String.cpp b/js/src/builtin/String.cpp
index 16e92b554c..1da2270cfb 100644
--- a/js/src/builtin/String.cpp
+++ b/js/src/builtin/String.cpp
@@ -566,15 +566,10 @@ static inline void CopyChars(CharT* to, const JSLinearString* from,
MOZ_ASSERT(begin + length <= from->length());
JS::AutoCheckCannotGC nogc;
- if constexpr (std::is_same_v<CharT, Latin1Char>) {
- MOZ_ASSERT(from->hasLatin1Chars());
+ if (from->hasLatin1Chars()) {
CopyChars(to, from->latin1Chars(nogc) + begin, length);
} else {
- if (from->hasLatin1Chars()) {
- CopyChars(to, from->latin1Chars(nogc) + begin, length);
- } else {
- CopyChars(to, from->twoByteChars(nogc) + begin, length);
- }
+ CopyChars(to, from->twoByteChars(nogc) + begin, length);
}
}
diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
index f762f28f3e..498fa1746d 100644
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1595,17 +1595,20 @@ static bool WasmLosslessInvoke(JSContext* cx, unsigned argc, Value* vp) {
JS_ReportErrorASCII(cx, "not enough arguments");
return false;
}
- if (!args.get(0).isObject()) {
+ if (!args.get(0).isObject() || !args.get(0).toObject().is<JSFunction>()) {
JS_ReportErrorASCII(cx, "argument is not an object");
return false;
}
- RootedFunction func(cx, args[0].toObject().maybeUnwrapIf<JSFunction>());
+ RootedFunction func(cx, &args[0].toObject().as<JSFunction>());
if (!func || !wasm::IsWasmExportedFunction(func)) {
JS_ReportErrorASCII(cx, "argument is not an exported wasm function");
return false;
}
+ // Switch to the function's realm
+ AutoRealm ar(cx, func);
+
// Get the instance and funcIndex for calling the function
wasm::Instance& instance = wasm::ExportedFunctionToInstance(func);
uint32_t funcIndex = wasm::ExportedFunctionToFuncIndex(func);
@@ -2042,6 +2045,95 @@ static bool WasmDisassemble(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
+static bool ToIonDumpContents(JSContext* cx, HandleValue value,
+ wasm::IonDumpContents* contents) {
+ RootedString option(cx, JS::ToString(cx, value));
+
+ if (!option) {
+ return false;
+ }
+
+ bool isEqual = false;
+ if (!JS_StringEqualsLiteral(cx, option, "mir", &isEqual) || isEqual) {
+ *contents = wasm::IonDumpContents::UnoptimizedMIR;
+ return isEqual;
+ } else if (!JS_StringEqualsLiteral(cx, option, "unopt-mir", &isEqual) ||
+ isEqual) {
+ *contents = wasm::IonDumpContents::UnoptimizedMIR;
+ return isEqual;
+ } else if (!JS_StringEqualsLiteral(cx, option, "opt-mir", &isEqual) ||
+ isEqual) {
+ *contents = wasm::IonDumpContents::OptimizedMIR;
+ return isEqual;
+ } else if (!JS_StringEqualsLiteral(cx, option, "lir", &isEqual) || isEqual) {
+ *contents = wasm::IonDumpContents::LIR;
+ return isEqual;
+ } else {
+ return false;
+ }
+}
+
+static bool WasmDumpIon(JSContext* cx, unsigned argc, Value* vp) {
+ if (!wasm::HasSupport(cx)) {
+ JS_ReportErrorASCII(cx, "wasm support unavailable");
+ return false;
+ }
+
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ args.rval().set(UndefinedValue());
+
+ SharedMem<uint8_t*> dataPointer;
+ size_t byteLength;
+ if (!args.get(0).isObject() || !IsBufferSource(args.get(0).toObjectOrNull(),
+ &dataPointer, &byteLength)) {
+ JS_ReportErrorASCII(cx, "argument is not a buffer source");
+ return false;
+ }
+
+ uint32_t targetFuncIndex;
+ if (!ToUint32(cx, args.get(1), &targetFuncIndex)) {
+ JS_ReportErrorASCII(cx, "argument is not a func index");
+ return false;
+ }
+
+ wasm::IonDumpContents contents = wasm::IonDumpContents::Default;
+ if (args.length() > 2 && !ToIonDumpContents(cx, args.get(2), &contents)) {
+ JS_ReportErrorASCII(cx, "argument is not a valid dump contents");
+ return false;
+ }
+
+ wasm::MutableBytes bytecode = cx->new_<wasm::ShareableBytes>();
+ if (!bytecode) {
+ return false;
+ }
+ if (!bytecode->append(dataPointer.unwrap(), byteLength)) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
+
+ UniqueChars error;
+ JSSprinter out(cx);
+ if (!out.init()) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
+
+ if (!wasm::DumpIonFunctionInModule(*bytecode, targetFuncIndex, contents, out,
+ &error)) {
+ if (error) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
+ JSMSG_WASM_COMPILE_ERROR, error.get());
+ return false;
+ }
+ ReportOutOfMemory(cx);
+ return false;
+ }
+
+ args.rval().set(StringValue(out.release(cx)));
+ return true;
+}
+
enum class Flag { Tier2Complete, Deserialized };
static bool WasmReturnFlag(JSContext* cx, unsigned argc, Value* vp, Flag flag) {
@@ -2073,7 +2165,6 @@ static bool WasmReturnFlag(JSContext* cx, unsigned argc, Value* vp, Flag flag) {
return true;
}
-#if defined(DEBUG)
static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
@@ -2082,10 +2173,6 @@ static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
- if (!cx->options().wasmTestMetadata()) {
- return false;
- }
-
if (args[0].toObject().is<WasmModuleObject>()) {
HashMap<const char*, uint32_t, mozilla::CStringHasher, SystemAllocPolicy>
hashmap = args[0]
@@ -2096,6 +2183,7 @@ static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) {
.metadataAnalysis(cx);
if (hashmap.empty()) {
JS_ReportErrorASCII(cx, "Metadata analysis has failed");
+ return false;
}
// metadataAnalysis returned a map of {key, value} with various statistics
@@ -2107,16 +2195,21 @@ static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) {
auto value = iter.get().value();
JSString* string = JS_NewStringCopyZ(cx, key);
+ if (!string) {
+ return false;
+ }
+
if (!props.append(
IdValuePair(NameToId(string->asLinear().toPropertyName(cx)),
NumberValue(value)))) {
- ReportOutOfMemory(cx);
return false;
}
}
- JSObject* results =
- NewPlainObjectWithUniqueNames(cx, props.begin(), props.length());
+ JSObject* results = NewPlainObjectWithUniqueNames(cx, props);
+ if (!results) {
+ return false;
+ }
args.rval().setObject(*results);
return true;
@@ -2127,7 +2220,6 @@ static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
-#endif
static bool WasmHasTier2CompilationCompleted(JSContext* cx, unsigned argc,
Value* vp) {
@@ -4523,7 +4615,9 @@ static bool ReadGeckoProfilingStack(JSContext* cx, unsigned argc, Value* vp) {
case JS::ProfilingFrameIterator::Frame_Ion:
frameKindStr = "ion";
break;
- case JS::ProfilingFrameIterator::Frame_Wasm:
+ case JS::ProfilingFrameIterator::Frame_WasmBaseline:
+ case JS::ProfilingFrameIterator::Frame_WasmIon:
+ case JS::ProfilingFrameIterator::Frame_WasmOther:
frameKindStr = "wasm";
break;
default:
@@ -5264,15 +5358,17 @@ class CustomSerializableObject : public NativeObject {
static ActivityLog* getThreadLog() {
if (!self.initialized() || !self.get()) {
self.infallibleInit();
+ AutoEnterOOMUnsafeRegion oomUnsafe;
self.set(js_new<ActivityLog>());
- MOZ_RELEASE_ASSERT(self.get());
+ if (!self.get()) {
+ oomUnsafe.crash("allocating activity log");
+ }
if (!TlsContext.get()->runtime()->atExit(
[](void* vpData) {
auto* log = static_cast<ActivityLog*>(vpData);
js_delete(log);
},
self.get())) {
- AutoEnterOOMUnsafeRegion oomUnsafe;
oomUnsafe.crash("atExit");
}
}
@@ -7199,6 +7295,8 @@ static bool CompileToStencil(JSContext* cx, uint32_t argc, Value* vp) {
}
CompileOptions options(cx);
+ options.setFile("<compileToStencil>");
+
RootedString displayURL(cx);
RootedString sourceMapURL(cx);
UniqueChars fileNameBytes;
@@ -7230,13 +7328,10 @@ static bool CompileToStencil(JSContext* cx, uint32_t argc, Value* vp) {
AutoReportFrontendContext fc(cx);
RefPtr<JS::Stencil> stencil;
- JS::CompilationStorage compileStorage;
if (isModule) {
- stencil =
- JS::CompileModuleScriptToStencil(&fc, options, srcBuf, compileStorage);
+ stencil = JS::CompileModuleScriptToStencil(&fc, options, srcBuf);
} else {
- stencil =
- JS::CompileGlobalScriptToStencil(&fc, options, srcBuf, compileStorage);
+ stencil = JS::CompileGlobalScriptToStencil(&fc, options, srcBuf);
}
if (!stencil) {
return false;
@@ -7368,6 +7463,8 @@ static bool CompileToStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
}
CompileOptions options(cx);
+ options.setFile("<compileToStencilXDR>");
+
RootedString displayURL(cx);
RootedString sourceMapURL(cx);
UniqueChars fileNameBytes;
@@ -9750,6 +9847,15 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE)
" ImportJitExit - wasm-to-jitted-JS stubs\n"
" all - all kinds, including obscure ones\n"),
+ JS_FN_HELP("wasmDumpIon", WasmDumpIon, 2, 0,
+"wasmDumpIon(bytecode, funcIndex, [, contents])\n",
+"wasmDumpIon(bytecode, funcIndex, [, contents])"
+" Returns a dump of compiling a function in the specified module with Ion."
+" The `contents` flag controls what is dumped. one of:"
+" `mir` | `unopt-mir`: Unoptimized MIR (the default)"
+" `opt-mir`: Optimized MIR"
+" `lir`: LIR"),
+
JS_FN_HELP("wasmHasTier2CompilationCompleted", WasmHasTier2CompilationCompleted, 1, 0,
"wasmHasTier2CompilationCompleted(module)",
" Returns a boolean indicating whether a given module has finished compiled code for tier2. \n"
@@ -9948,11 +10054,9 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE)
" element's edge is the node of the i+1'th array element; the destination of\n"
" the last array element is implicitly |target|.\n"),
-#if defined(DEBUG)
JS_FN_HELP("wasmMetadataAnalysis", wasmMetadataAnalysis, 1, 0,
"wasmMetadataAnalysis(wasmObject)",
" Prints an analysis of the size of metadata on this wasm object.\n"),
-#endif
#if defined(DEBUG) || defined(JS_JITSPEW)
JS_FN_HELP("dumpObject", DumpObject, 1, 0,
diff --git a/js/src/builtin/intl/NumberFormat.js b/js/src/builtin/intl/NumberFormat.js
index be3b74a8ac..6dc77fb639 100644
--- a/js/src/builtin/intl/NumberFormat.js
+++ b/js/src/builtin/intl/NumberFormat.js
@@ -190,7 +190,7 @@ function UnwrapNumberFormat(nf) {
*
* Applies digit options used for number formatting onto the intl object.
*
- * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6
+ * ES2024 Intl draft rev a1db4567870dbe505121a4255f1210338757190a
*/
function SetNumberFormatDigitOptions(
lazyData,
@@ -216,15 +216,6 @@ function SetNumberFormatDigitOptions(
lazyData.minimumIntegerDigits = mnid;
// Step 7.
- var roundingPriority = GetOption(
- options,
- "roundingPriority",
- "string",
- ["auto", "morePrecision", "lessPrecision"],
- "auto"
- );
-
- // Step 8.
var roundingIncrement = GetNumberOption(
options,
"roundingIncrement",
@@ -233,7 +224,7 @@ function SetNumberFormatDigitOptions(
1
);
- // Step 9.
+ // Step 8.
switch (roundingIncrement) {
case 1:
case 2:
@@ -259,7 +250,7 @@ function SetNumberFormatDigitOptions(
);
}
- // Step 10.
+ // Step 9.
var roundingMode = GetOption(
options,
"roundingMode",
@@ -278,6 +269,15 @@ function SetNumberFormatDigitOptions(
"halfExpand"
);
+ // Step 10.
+ var roundingPriority = GetOption(
+ options,
+ "roundingPriority",
+ "string",
+ ["auto", "morePrecision", "lessPrecision"],
+ "auto"
+ );
+
// Step 11.
var trailingZeroDisplay = GetOption(
options,
@@ -303,52 +303,52 @@ function SetNumberFormatDigitOptions(
// Step 16.
lazyData.trailingZeroDisplay = trailingZeroDisplay;
- // Steps 17-18.
+ // Step 17.
var hasSignificantDigits = mnsd !== undefined || mxsd !== undefined;
- // Step 19-20.
+ // Step 28.
var hasFractionDigits = mnfd !== undefined || mxfd !== undefined;
- // Steps 21 and 23.a.
+ // Steps 19 and 21.a.
var needSignificantDigits =
roundingPriority !== "auto" || hasSignificantDigits;
- // Steps 22 and 23.b.i.
+ // Steps 20 and 21.b.i.
var needFractionalDigits =
roundingPriority !== "auto" ||
!(hasSignificantDigits || (!hasFractionDigits && notation === "compact"));
- // Step 24.
+ // Step 22.
if (needSignificantDigits) {
- // Step 24.a.
+ // Step 22.a.
if (hasSignificantDigits) {
- // Step 24.a.i.
+ // Step 22.a.i.
mnsd = DefaultNumberOption(mnsd, 1, 21, 1);
lazyData.minimumSignificantDigits = mnsd;
- // Step 24.a.ii.
+ // Step 22.a.ii.
mxsd = DefaultNumberOption(mxsd, mnsd, 21, 21);
lazyData.maximumSignificantDigits = mxsd;
} else {
- // Step 24.b.i.
+ // Step 22.b.i.
lazyData.minimumSignificantDigits = 1;
- // Step 24.b.ii.
+ // Step 22.b.ii.
lazyData.maximumSignificantDigits = 21;
}
}
- // Step 25.
+ // Step 23.
if (needFractionalDigits) {
- // Step 25.a.
+ // Step 23.a.
if (hasFractionDigits) {
- // Step 25.a.i.
+ // Step 23.a.i.
mnfd = DefaultNumberOption(mnfd, 0, 100, undefined);
- // Step 25.a.ii.
+ // Step 23.a.ii.
mxfd = DefaultNumberOption(mxfd, 0, 100, undefined);
- // Step 25.a.iii.
+ // Step 23.a.iii.
if (mnfd === undefined) {
assert(
mxfd !== undefined,
@@ -357,31 +357,31 @@ function SetNumberFormatDigitOptions(
mnfd = std_Math_min(mnfdDefault, mxfd);
}
- // Step 25.a.iv.
+ // Step 23.a.iv.
else if (mxfd === undefined) {
mxfd = std_Math_max(mxfdDefault, mnfd);
}
- // Step 25.a.v.
+ // Step 23.a.v.
else if (mnfd > mxfd) {
ThrowRangeError(JSMSG_INVALID_DIGITS_VALUE, mxfd);
}
- // Step 25.a.vi.
+ // Step 23.a.vi.
lazyData.minimumFractionDigits = mnfd;
- // Step 25.a.vii.
+ // Step 23.a.vii.
lazyData.maximumFractionDigits = mxfd;
} else {
- // Step 25.b.i.
+ // Step 23.b.i.
lazyData.minimumFractionDigits = mnfdDefault;
- // Step 25.b.ii.
+ // Step 23.b.ii.
lazyData.maximumFractionDigits = mxfdDefault;
}
}
- // Steps 26-30.
+ // Steps 24-28.
if (!needSignificantDigits && !needFractionalDigits) {
assert(!hasSignificantDigits, "bad significant digits in fallback case");
assert(
@@ -393,23 +393,23 @@ function SetNumberFormatDigitOptions(
`bad notation in fallback case: ${notation}`
);
- // Steps 26.a-e.
+ // Steps 24.a-f.
lazyData.minimumFractionDigits = 0;
lazyData.maximumFractionDigits = 0;
lazyData.minimumSignificantDigits = 1;
lazyData.maximumSignificantDigits = 2;
lazyData.roundingPriority = "morePrecision";
} else {
- // Steps 27-30.
+ // Steps 25-28.
//
// Our implementation stores |roundingPriority| instead of using
// [[RoundingType]].
lazyData.roundingPriority = roundingPriority;
}
- // Step 31.
+ // Step 29.
if (roundingIncrement !== 1) {
- // Step 31.a.
+ // Step 29.a.
//
// [[RoundingType]] is `fractionDigits` if |roundingPriority| is equal to
// "auto" and |hasSignificantDigits| is false.
@@ -428,7 +428,7 @@ function SetNumberFormatDigitOptions(
);
}
- // Step 31.b.
+ // Step 29.b.
//
// Minimum and maximum fraction digits must be equal.
if (
@@ -1128,7 +1128,7 @@ function Intl_NumberFormat_formatRangeToParts(start, end) {
*
* Returns the resolved options for a NumberFormat object.
*
- * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6
+ * ES2024 Intl draft rev a1db4567870dbe505121a4255f1210338757190a
*/
function Intl_NumberFormat_resolvedOptions() {
// Steps 1-3.
@@ -1244,20 +1244,15 @@ function Intl_NumberFormat_resolvedOptions() {
}
DefineDataProperty(result, "signDisplay", internals.signDisplay);
- DefineDataProperty(result, "roundingMode", internals.roundingMode);
DefineDataProperty(result, "roundingIncrement", internals.roundingIncrement);
+ DefineDataProperty(result, "roundingMode", internals.roundingMode);
+ DefineDataProperty(result, "roundingPriority", internals.roundingPriority);
DefineDataProperty(
result,
"trailingZeroDisplay",
internals.trailingZeroDisplay
);
- // Steps 6-8.
- //
- // Our implementation doesn't use [[RoundingType]], but instead directly
- // stores the computed `roundingPriority` value.
- DefineDataProperty(result, "roundingPriority", internals.roundingPriority);
-
- // Step 9.
+ // Step 6.
return result;
}
diff --git a/js/src/builtin/intl/PluralRules.js b/js/src/builtin/intl/PluralRules.js
index 1dbf6656df..260fdbd568 100644
--- a/js/src/builtin/intl/PluralRules.js
+++ b/js/src/builtin/intl/PluralRules.js
@@ -339,7 +339,7 @@ function Intl_PluralRules_selectRange(start, end) {
*
* Returns the resolved options for a PluralRules object.
*
- * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6
+ * ES2024 Intl draft rev a1db4567870dbe505121a4255f1210338757190a
*/
function Intl_PluralRules_resolvedOptions() {
// Step 1.
@@ -359,7 +359,20 @@ function Intl_PluralRules_resolvedOptions() {
var internals = getPluralRulesInternals(pluralRules);
- // Steps 3-4.
+ // Step 4.
+ var internalsPluralCategories = internals.pluralCategories;
+ if (internalsPluralCategories === null) {
+ internalsPluralCategories = intl_GetPluralCategories(pluralRules);
+ internals.pluralCategories = internalsPluralCategories;
+ }
+
+ // Step 5.b.
+ var pluralCategories = [];
+ for (var i = 0; i < internalsPluralCategories.length; i++) {
+ DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]);
+ }
+
+ // Steps 3 and 5.
var result = {
locale: internals.locale,
type: internals.type,
@@ -406,35 +419,16 @@ function Intl_PluralRules_resolvedOptions() {
);
}
- DefineDataProperty(result, "roundingMode", internals.roundingMode);
+ DefineDataProperty(result, "pluralCategories", pluralCategories);
DefineDataProperty(result, "roundingIncrement", internals.roundingIncrement);
+ DefineDataProperty(result, "roundingMode", internals.roundingMode);
+ DefineDataProperty(result, "roundingPriority", internals.roundingPriority);
DefineDataProperty(
result,
"trailingZeroDisplay",
internals.trailingZeroDisplay
);
- // Step 5.
- var internalsPluralCategories = internals.pluralCategories;
- if (internalsPluralCategories === null) {
- internalsPluralCategories = intl_GetPluralCategories(pluralRules);
- internals.pluralCategories = internalsPluralCategories;
- }
-
- var pluralCategories = [];
- for (var i = 0; i < internalsPluralCategories.length; i++) {
- DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]);
- }
-
// Step 6.
- DefineDataProperty(result, "pluralCategories", pluralCategories);
-
- // Steps 7-9.
- //
- // Our implementation doesn't use [[RoundingType]], but instead directly
- // stores the computed `roundingPriority` value.
- DefineDataProperty(result, "roundingPriority", internals.roundingPriority);
-
- // Step 10.
return result;
}
diff --git a/js/src/builtin/intl/make_intl_data.py b/js/src/builtin/intl/make_intl_data.py
index 7042c0a005..a8357445c4 100755
--- a/js/src/builtin/intl/make_intl_data.py
+++ b/js/src/builtin/intl/make_intl_data.py
@@ -2213,7 +2213,7 @@ def listIANAFiles(tzdataDir):
def readIANAFiles(tzdataDir, files):
"""Read all IANA time zone files from the given iterable."""
- nameSyntax = "[\w/+\-]+"
+ nameSyntax = r"[\w/+\-]+"
pZone = re.compile(r"Zone\s+(?P<name>%s)\s+.*" % nameSyntax)
pLink = re.compile(
r"Link\s+(?P<target>%s)\s+(?P<name>%s)(?:\s+#.*)?" % (nameSyntax, nameSyntax)
@@ -2310,7 +2310,7 @@ def readICUResourceFile(filename):
maybeMultiComments = r"(?:/\*[^*]*\*/)*"
maybeSingleComment = r"(?://.*)?"
lineStart = "^%s" % maybeMultiComments
- lineEnd = "%s\s*%s$" % (maybeMultiComments, maybeSingleComment)
+ lineEnd = r"%s\s*%s$" % (maybeMultiComments, maybeSingleComment)
return re.compile(r"\s*".join(chain([lineStart], args, [lineEnd])))
tableName = r'(?P<quote>"?)(?P<name>.+?)(?P=quote)'
@@ -2554,7 +2554,7 @@ def icuTzDataVersion(icuTzDir):
zoneinfo = os.path.join(icuTzDir, "zoneinfo64.txt")
if not os.path.isfile(zoneinfo):
raise RuntimeError("file not found: %s" % zoneinfo)
- version = searchInFile("^//\s+tz version:\s+([0-9]{4}[a-z])$", zoneinfo)
+ version = searchInFile(r"^//\s+tz version:\s+([0-9]{4}[a-z])$", zoneinfo)
if version is None:
raise RuntimeError(
"%s does not contain a valid tzdata version string" % zoneinfo
@@ -3711,7 +3711,7 @@ const allUnits = {};
""".format(
all_units_array
)
- + """
+ + r"""
// Test only sanctioned unit identifiers are allowed.
for (const typeAndUnit of allUnits) {
diff --git a/js/src/builtin/temporal/PlainDate.cpp b/js/src/builtin/temporal/PlainDate.cpp
index 759456c9cc..a4ad0e418f 100644
--- a/js/src/builtin/temporal/PlainDate.cpp
+++ b/js/src/builtin/temporal/PlainDate.cpp
@@ -2295,8 +2295,7 @@ static bool PlainDate_getISOFields(JSContext* cx, const CallArgs& args) {
}
// Step 8.
- auto* obj =
- NewPlainObjectWithUniqueNames(cx, fields.begin(), fields.length());
+ auto* obj = NewPlainObjectWithUniqueNames(cx, fields);
if (!obj) {
return false;
}
diff --git a/js/src/builtin/temporal/PlainDateTime.cpp b/js/src/builtin/temporal/PlainDateTime.cpp
index 8861b484bd..8f137cfe43 100644
--- a/js/src/builtin/temporal/PlainDateTime.cpp
+++ b/js/src/builtin/temporal/PlainDateTime.cpp
@@ -2507,8 +2507,7 @@ static bool PlainDateTime_getISOFields(JSContext* cx, const CallArgs& args) {
}
// Step 14.
- auto* obj =
- NewPlainObjectWithUniqueNames(cx, fields.begin(), fields.length());
+ auto* obj = NewPlainObjectWithUniqueNames(cx, fields);
if (!obj) {
return false;
}
diff --git a/js/src/builtin/temporal/PlainMonthDay.cpp b/js/src/builtin/temporal/PlainMonthDay.cpp
index f97b7ad68c..0896100a3f 100644
--- a/js/src/builtin/temporal/PlainMonthDay.cpp
+++ b/js/src/builtin/temporal/PlainMonthDay.cpp
@@ -903,8 +903,7 @@ static bool PlainMonthDay_getISOFields(JSContext* cx, const CallArgs& args) {
}
// Step 8.
- auto* obj =
- NewPlainObjectWithUniqueNames(cx, fields.begin(), fields.length());
+ auto* obj = NewPlainObjectWithUniqueNames(cx, fields);
if (!obj) {
return false;
}
diff --git a/js/src/builtin/temporal/PlainTime.cpp b/js/src/builtin/temporal/PlainTime.cpp
index 9501b5853b..bf35b9d93e 100644
--- a/js/src/builtin/temporal/PlainTime.cpp
+++ b/js/src/builtin/temporal/PlainTime.cpp
@@ -2432,8 +2432,7 @@ static bool PlainTime_getISOFields(JSContext* cx, const CallArgs& args) {
}
// Step 10.
- auto* obj =
- NewPlainObjectWithUniqueNames(cx, fields.begin(), fields.length());
+ auto* obj = NewPlainObjectWithUniqueNames(cx, fields);
if (!obj) {
return false;
}
diff --git a/js/src/builtin/temporal/PlainYearMonth.cpp b/js/src/builtin/temporal/PlainYearMonth.cpp
index a4e2f8f9e4..b95efd3179 100644
--- a/js/src/builtin/temporal/PlainYearMonth.cpp
+++ b/js/src/builtin/temporal/PlainYearMonth.cpp
@@ -1534,8 +1534,7 @@ static bool PlainYearMonth_getISOFields(JSContext* cx, const CallArgs& args) {
}
// Step 8.
- auto* obj =
- NewPlainObjectWithUniqueNames(cx, fields.begin(), fields.length());
+ auto* obj = NewPlainObjectWithUniqueNames(cx, fields);
if (!obj) {
return false;
}
diff --git a/js/src/builtin/temporal/ZonedDateTime.cpp b/js/src/builtin/temporal/ZonedDateTime.cpp
index 690ff223b1..92842a9626 100644
--- a/js/src/builtin/temporal/ZonedDateTime.cpp
+++ b/js/src/builtin/temporal/ZonedDateTime.cpp
@@ -3958,8 +3958,7 @@ static bool ZonedDateTime_getISOFields(JSContext* cx, const CallArgs& args) {
}
// Step 22.
- auto* obj =
- NewPlainObjectWithUniqueNames(cx, fields.begin(), fields.length());
+ auto* obj = NewPlainObjectWithUniqueNames(cx, fields);
if (!obj) {
return false;
}