Skip to content

Commit b8588d0

Browse files
committed
bring up test262 test passing results, bug fixing, refactoring, groundwork for Temporal.PlainTime, WIP Temporal.prototype.round implementations.. probably should have committed more frequently lol
1 parent 6078708 commit b8588d0

File tree

20 files changed

+601
-159
lines changed

20 files changed

+601
-159
lines changed

nova_vm/src/builtin_strings

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ encodeURIComponent
113113
endsWith
114114
entries
115115
enumerable
116+
#[cfg(feature = "temporal")]epochMilliseconds
117+
#[cfg(feature = "temporal")]epochNanoseconds
116118
EPSILON
117119
#[cfg(feature = "temporal")]equals
118120
Error
@@ -149,8 +151,8 @@ for
149151
forEach
150152
freeze
151153
from
152-
fromEpochNanoseconds
153-
fromEpochMilliseconds
154+
#[cfg(feature = "temporal")]fromEpochNanoseconds
155+
#[cfg(feature = "temporal")]fromEpochMilliseconds
154156
fromCharCode
155157
fromCodePoint
156158
fromEntries
@@ -186,8 +188,8 @@ get size
186188
#[cfg(feature = "array-buffer")]getBigUint64
187189
#[cfg(feature = "date")]getDate
188190
#[cfg(feature = "date")]getDay
189-
#[cfg(feature = "temporal")]getEpochMilliseconds
190-
#[cfg(feature = "temporal")]getEpochNanoSeconds
191+
#[cfg(feature = "temporal")]get epochMilliseconds
192+
#[cfg(feature = "temporal")]get epochNanoseconds
191193
#[cfg(feature = "proposal-float16array")]getFloat16
192194
#[cfg(feature = "array-buffer")]getFloat32
193195
#[cfg(feature = "array-buffer")]getFloat64
@@ -320,6 +322,7 @@ parseFloat
320322
parseInt
321323
#[cfg(feature = "proposal-atomics-microwait")]pause
322324
#[cfg(feature = "math")]PI
325+
#[cfg(feature = "temporal")]PlainTime
323326
pop
324327
POSITIVE_INFINITY
325328
#[cfg(feature = "math")]pow

nova_vm/src/ecmascript/builtins/ordinary.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use caches::{CacheToPopulate, Caches, PropertyLookupCache, PropertyOffset};
1717
use crate::ecmascript::builtins::data_view::data::SharedDataViewRecord;
1818
#[cfg(feature = "temporal")]
1919
use crate::ecmascript::builtins::temporal::instant::data::InstantHeapData;
20+
use crate::ecmascript::builtins::temporal::plain_time::data::PlainTimeHeapData;
2021
use crate::{
2122
ecmascript::{
2223
abstract_operations::operations_on_objects::{
@@ -1686,6 +1687,8 @@ pub(crate) fn ordinary_object_create_with_intrinsics<'a>(
16861687
ProtoIntrinsics::TemporalInstant => {
16871688
agent.heap.create(InstantHeapData::default()).into_object()
16881689
}
1690+
#[cfg(feature = "temporal")]
1691+
ProtoIntrinsics::TemporalPlainTime => todo!(),
16891692
ProtoIntrinsics::TypeError => agent
16901693
.heap
16911694
.create(ErrorHeapData::new(ExceptionType::TypeError, None, None))
@@ -2074,6 +2077,10 @@ fn get_intrinsic_constructor<'a>(
20742077
ProtoIntrinsics::WeakSet => Some(intrinsics.weak_set().into_function()),
20752078
#[cfg(feature = "temporal")]
20762079
ProtoIntrinsics::TemporalInstant => Some(intrinsics.temporal_instant().into_function()),
2080+
#[cfg(feature = "temporal")]
2081+
ProtoIntrinsics::TemporalPlainTime => {
2082+
Some(intrinsics.temporal_plain_time().into_function())
2083+
}
20772084
}
20782085
}
20792086

nova_vm/src/ecmascript/builtins/temporal.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
pub mod duration;
66
pub mod error;
77
pub mod instant;
8+
pub mod options;
9+
pub mod plain_time;
810

911
use crate::{
1012
ecmascript::{
@@ -16,27 +18,45 @@ use crate::{
1618
heap::WellKnownSymbolIndexes,
1719
};
1820

19-
pub(crate) struct TemporalObject;
21+
pub(crate) struct Temporal;
2022

21-
impl TemporalObject {
23+
impl Temporal {
2224
pub fn create_intrinsic(agent: &mut Agent, realm: Realm<'static>, _: NoGcScope) {
2325
let intrinsics = agent.get_realm_record_by_id(realm).intrinsics();
2426
let object_prototype = intrinsics.object_prototype();
2527
let this = intrinsics.temporal();
2628

27-
let temporal_instant_constructor = intrinsics.temporal_instant();
29+
let instant_constructor = intrinsics.temporal_instant();
30+
let plain_time_constructor = intrinsics.temporal_plain_time();
2831

2932
OrdinaryObjectBuilder::new_intrinsic_object(agent, realm, this)
30-
.with_property_capacity(2)
33+
.with_property_capacity(3)
3134
.with_prototype(object_prototype)
35+
// 1.2.1 Temporal.Instant ( . . . )
3236
.with_property(|builder| {
3337
builder
3438
.with_key(BUILTIN_STRING_MEMORY.Instant.into())
35-
.with_value(temporal_instant_constructor.into_value())
39+
.with_value(instant_constructor.into_value())
3640
.with_enumerable(false)
37-
.with_configurable(false)
41+
.with_configurable(true)
42+
.build()
43+
})
44+
// 1.2.2 Temporal.PlainDateTime ( . . . )
45+
// 1.2.3 Temporal.PlainDate ( . . . )
46+
// 1.2.4 Temporal.PlainTime ( . . . )
47+
.with_property(|builder| {
48+
builder
49+
.with_key(BUILTIN_STRING_MEMORY.PlainTime.into())
50+
.with_value(plain_time_constructor.into_value())
51+
.with_enumerable(false)
52+
.with_configurable(true)
3853
.build()
3954
})
55+
// 1.2.5 Temporal.PlainYearMonth ( . . . )
56+
// 1.2.6 Temporal.PlainMonthDay ( . . . )
57+
// 1.2.7 Temporal.Duration ( . . . )
58+
// 1.2.8 Temporal.ZonedDateTime ( . . . )
59+
// 1.3.1 Temporal.Now
4060
.with_property(|builder| {
4161
builder
4262
.with_key(WellKnownSymbolIndexes::ToStringTag.into())

nova_vm/src/ecmascript/builtins/temporal/instant.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use crate::{
1212
ecmascript::{
1313
abstract_operations::type_conversion::{PreferredType, to_primitive_object},
1414
builtins::{
15-
ordinary::ordinary_create_from_constructor, temporal::duration::to_temporal_duration,
15+
ordinary::ordinary_create_from_constructor,
16+
temporal::{duration::to_temporal_duration, error::temporal_err_to_js_err},
1617
},
1718
execution::{
1819
JsResult, ProtoIntrinsics,
@@ -229,26 +230,38 @@ fn create_temporal_instant<'gc>(
229230
fn to_temporal_instant<'gc>(
230231
agent: &mut Agent,
231232
item: Value,
232-
gc: GcScope<'gc, '_>,
233+
mut gc: GcScope<'gc, '_>,
233234
) -> JsResult<'gc, temporal_rs::Instant> {
234235
let item = item.bind(gc.nogc());
235236
// 1. If item is an Object, then
236237
let item = if let Ok(item) = Object::try_from(item) {
237238
// a. If item has an [[InitializedTemporalInstant]] or [[InitializedTemporalZonedDateTime]]
238-
// internal slot, then TODO: TemporalZonedDateTime::try_from(item)
239+
// internal slot, then
240+
// TODO: TemporalZonedDateTime::try_from(item)
239241
if let Ok(item) = TemporalInstant::try_from(item) {
240242
// i. Return ! CreateTemporalInstant(item.[[EpochNanoseconds]]).
241243
return Ok(agent[item].instant);
242244
}
243245
// b. NOTE: This use of ToPrimitive allows Instant-like objects to be converted.
244246
// c. Set item to ? ToPrimitive(item, string).
245-
to_primitive_object(agent, item.unbind(), Some(PreferredType::String), gc)?
247+
to_primitive_object(
248+
agent,
249+
item.unbind(),
250+
Some(PreferredType::String),
251+
gc.reborrow(),
252+
)
253+
.unbind()?
254+
.bind(gc.nogc())
246255
} else {
247256
Primitive::try_from(item).unwrap()
248257
};
249258
// 2. If item is not a String, throw a TypeError exception.
250259
let Ok(item) = String::try_from(item) else {
251-
todo!() // TypeErrror
260+
return Err(agent.throw_exception_with_static_message(
261+
ExceptionType::TypeError,
262+
"Item is not a String",
263+
gc.into_nogc(),
264+
));
252265
};
253266
// 3. Let parsed be ? ParseISODateTime(item, « TemporalInstantString »).
254267
// 4. Assert: Either parsed.[[TimeZone]].[[OffsetString]] is not empty or
@@ -264,7 +277,8 @@ fn to_temporal_instant<'gc>(
264277
// 9. Let epochNanoseconds be GetUTCEpochNanoseconds(balanced).
265278
// 10. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
266279
// 11. Return ! CreateTemporalInstant(epochNanoseconds).
267-
let parsed = temporal_rs::Instant::from_utf8(item.as_bytes(agent)).unwrap();
280+
let parsed = temporal_rs::Instant::from_utf8(item.as_bytes(agent))
281+
.map_err(|e| temporal_err_to_js_err(agent, e, gc.into_nogc()))?;
268282
Ok(parsed)
269283
}
270284

nova_vm/src/ecmascript/builtins/temporal/instant/instant_constructor.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ impl Builtin for TemporalInstantConstructor {
2828
const LENGTH: u8 = 1;
2929
const BEHAVIOUR: Behaviour = Behaviour::Constructor(TemporalInstantConstructor::constructor);
3030
}
31-
3231
impl BuiltinIntrinsicConstructor for TemporalInstantConstructor {
3332
const INDEX: IntrinsicConstructorIndexes = IntrinsicConstructorIndexes::TemporalInstant;
3433
}
@@ -97,14 +96,13 @@ impl TemporalInstantConstructor {
9796
new_target = unsafe { scoped_new_target.take(agent) }.bind(gc.nogc());
9897
epoch_nanoseconds
9998
};
100-
10199
// 3. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
102100
let Some(epoch_nanoseconds) = epoch_nanoseconds
103101
.try_into_i128(agent)
104102
.and_then(|nanoseconds| temporal_rs::Instant::try_new(nanoseconds).ok())
105103
else {
106104
return Err(agent.throw_exception_with_static_message(
107-
ExceptionType::TypeError,
105+
ExceptionType::RangeError,
108106
"value out of range",
109107
gc.into_nogc(),
110108
));
@@ -214,7 +212,7 @@ impl TemporalInstantConstructor {
214212
mut gc: GcScope<'gc, '_>,
215213
) -> JsResult<'gc, Value<'gc>> {
216214
let one = args.get(0).bind(gc.nogc());
217-
let two = args.get(0).bind(gc.nogc());
215+
let two = args.get(1).bind(gc.nogc());
218216
let two = two.scope(agent, gc.nogc());
219217
// 1. Set one to ? ToTemporalInstant(one).
220218
let one_instant = to_temporal_instant(agent, one.unbind(), gc.reborrow()).unbind()?;

0 commit comments

Comments
 (0)