Skip to content

Commit 27e925c

Browse files
Merge pull request #8 from sebastianjacmatt/duration-and-durationproto
Duration and durationproto
2 parents 1996577 + 273d87e commit 27e925c

File tree

17 files changed

+347
-43
lines changed

17 files changed

+347
-43
lines changed

nova_vm/src/builtin_strings

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ description
108108
#[cfg(feature = "array-buffer")]detached
109109
done
110110
#[cfg(feature = "regexp")]dotAll
111+
#[cfg(feature="temporal")]Duration
111112
#[cfg(feature = "math")]E
112113
encodeURI
113114
encodeURIComponent
@@ -446,6 +447,7 @@ Symbol.toStringTag
446447
Symbol.unscopables
447448
SyntaxError
448449
#[cfg(feature = "temporal")]Temporal
450+
#[cfg(feature = "temporal")]Temporal.Duration
449451
#[cfg(feature = "temporal")]Temporal.Instant
450452
#[cfg(feature = "math")]tan
451453
#[cfg(feature = "math")]tanh

nova_vm/src/ecmascript/builtins/ordinary.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ use caches::{CacheToPopulate, Caches, PropertyLookupCache, PropertyOffset};
1616
#[cfg(feature = "shared-array-buffer")]
1717
use crate::ecmascript::builtins::data_view::data::SharedDataViewRecord;
1818
#[cfg(feature = "temporal")]
19-
use crate::ecmascript::builtins::temporal::instant::data::InstantHeapData;
20-
use crate::ecmascript::builtins::temporal::plain_time::data::PlainTimeHeapData;
19+
use crate::ecmascript::builtins::temporal::{
20+
instant::data::InstantHeapData,
21+
plain_time::data::PlainTimeHeapData,
22+
duration::data::DurationHeapData
23+
};
2124
use crate::{
2225
ecmascript::{
2326
abstract_operations::operations_on_objects::{
@@ -1688,6 +1691,10 @@ pub(crate) fn ordinary_object_create_with_intrinsics<'a>(
16881691
agent.heap.create(InstantHeapData::default()).into_object()
16891692
}
16901693
#[cfg(feature = "temporal")]
1694+
ProtoIntrinsics::TemporalDuration => {
1695+
agent.heap.create(DurationHeapData::default()).into_object()
1696+
}
1697+
#[cfg(feature = "temporal")]
16911698
ProtoIntrinsics::TemporalPlainTime => agent
16921699
.heap
16931700
.create(PlainTimeHeapData::default())
@@ -2081,6 +2088,8 @@ fn get_intrinsic_constructor<'a>(
20812088
#[cfg(feature = "temporal")]
20822089
ProtoIntrinsics::TemporalInstant => Some(intrinsics.temporal_instant().into_function()),
20832090
#[cfg(feature = "temporal")]
2091+
ProtoIntrinsics::TemporalDuration => Some(intrinsics.temporal_duration().into_function()),
2092+
#[cfg(feature = "temporal")]
20842093
ProtoIntrinsics::TemporalPlainTime => {
20852094
Some(intrinsics.temporal_plain_time().into_function())
20862095
}

nova_vm/src/ecmascript/builtins/temporal.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ impl Temporal {
3737
let this = intrinsics.temporal();
3838

3939
let instant_constructor = intrinsics.temporal_instant();
40+
let duration_constructor = intrinsics.temporal_duration();
4041
let plain_time_constructor = intrinsics.temporal_plain_time();
4142

4243
OrdinaryObjectBuilder::new_intrinsic_object(agent, realm, this)
@@ -65,6 +66,14 @@ impl Temporal {
6566
// 1.2.5 Temporal.PlainYearMonth ( . . . )
6667
// 1.2.6 Temporal.PlainMonthDay ( . . . )
6768
// 1.2.7 Temporal.Duration ( . . . )
69+
.with_property(|builder| {
70+
builder
71+
.with_key(BUILTIN_STRING_MEMORY.Duration.into())
72+
.with_value(duration_constructor.into_value())
73+
.with_enumerable(false)
74+
.with_configurable(true)
75+
.build()
76+
})
6877
// 1.2.8 Temporal.ZonedDateTime ( . . . )
6978
// 1.3.1 Temporal.Now
7079
.with_property(|builder| {

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

Lines changed: 85 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
1+
pub(crate) mod data;
2+
pub mod duration_constructor;
3+
pub mod duration_prototype;
4+
15
use crate::{
26
ecmascript::{
37
abstract_operations::{
48
operations_on_objects::get, type_conversion::to_integer_if_integral,
59
},
6-
execution::{Agent, JsResult, agent::ExceptionType},
7-
types::{BUILTIN_STRING_MEMORY, Object, String, Value},
10+
execution::{Agent, JsResult, ProtoIntrinsics, agent::ExceptionType},
11+
types::{
12+
BUILTIN_STRING_MEMORY, InternalMethods, InternalSlots, Object, OrdinaryObject, String,
13+
Value,
14+
},
815
},
916
engine::{
1017
context::{Bindable, GcScope, NoGcScope, bindable_handle},
11-
rootable::Scopable,
18+
rootable::{HeapRootData, HeapRootRef, Rootable, Scopable},
19+
},
20+
heap::{
21+
CompactionLists, CreateHeapData, Heap, HeapMarkAndSweep, HeapSweepWeakReference,
22+
WorkQueues, indexes::BaseIndex,
1223
},
13-
heap::indexes::BaseIndex,
1424
};
1525
use core::ops::{Index, IndexMut};
1626

17-
pub(crate) mod data;
1827
use self::data::DurationHeapData;
1928
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2029
#[repr(transparent)]
@@ -35,42 +44,49 @@ impl TemporalDuration<'_> {
3544
bindable_handle!(TemporalDuration);
3645

3746
impl<'a> From<TemporalDuration<'a>> for Value<'a> {
38-
fn from(_value: TemporalDuration<'a>) -> Self {
39-
todo!()
40-
//Value::Duration(value)
47+
fn from(value: TemporalDuration<'a>) -> Self {
48+
Value::Duration(value)
4149
}
4250
}
4351
impl<'a> From<TemporalDuration<'a>> for Object<'a> {
44-
fn from(_value: TemporalDuration<'a>) -> Self {
45-
todo!()
46-
//Object::Duration(value)
52+
fn from(value: TemporalDuration<'a>) -> Self {
53+
Object::Duration(value)
4754
}
4855
}
4956
impl<'a> TryFrom<Value<'a>> for TemporalDuration<'a> {
5057
type Error = ();
5158

52-
fn try_from(_value: Value<'a>) -> Result<Self, ()> {
53-
todo!()
54-
// match value {
55-
// Value::Duration(idx) => Ok(idx),
56-
// _ => Err(()),
57-
// }
59+
fn try_from(value: Value<'a>) -> Result<Self, ()> {
60+
match value {
61+
Value::Duration(idx) => Ok(idx),
62+
_ => Err(()),
63+
}
64+
}
65+
}
66+
67+
impl<'a> InternalSlots<'a> for TemporalDuration<'a> {
68+
const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::TemporalDuration;
69+
fn get_backing_object(self, agent: &Agent) -> Option<OrdinaryObject<'static>> {
70+
agent[self].object_index
71+
}
72+
fn set_backing_object(self, agent: &mut Agent, backing_object: OrdinaryObject<'static>) {
73+
assert!(agent[self].object_index.replace(backing_object).is_none());
5874
}
5975
}
6076

77+
impl<'a> InternalMethods<'a> for TemporalDuration<'a> {}
78+
6179
impl Index<TemporalDuration<'_>> for Agent {
6280
type Output = DurationHeapData<'static>;
6381

64-
fn index(&self, _index: TemporalDuration<'_>) -> &Self::Output {
65-
unimplemented!()
66-
//&self.heap.durations[index]
82+
fn index(&self, index: TemporalDuration<'_>) -> &Self::Output {
83+
&self.heap.durations[index]
6784
}
6885
}
6986

7087
impl IndexMut<TemporalDuration<'_>> for Agent {
71-
fn index_mut(&mut self, _index: TemporalDuration) -> &mut Self::Output {
72-
unimplemented!()
73-
//&mut self.heap.durations[index]
88+
fn index_mut(&mut self, index: TemporalDuration) -> &mut Self::Output {
89+
&mut self.heap.durations[index]
7490
}
7591
}
7692

@@ -89,6 +105,52 @@ impl IndexMut<TemporalDuration<'_>> for Vec<DurationHeapData<'static>> {
89105
.expect("heap access out of bounds")
90106
}
91107
}
108+
109+
impl Rootable for TemporalDuration<'_> {
110+
type RootRepr = HeapRootRef;
111+
112+
fn to_root_repr(value: Self) -> Result<Self::RootRepr, HeapRootData> {
113+
Err(HeapRootData::Duration(value.unbind()))
114+
}
115+
116+
fn from_root_repr(value: &Self::RootRepr) -> Result<Self, HeapRootRef> {
117+
Err(*value)
118+
}
119+
120+
fn from_heap_ref(heap_ref: HeapRootRef) -> Self::RootRepr {
121+
heap_ref
122+
}
123+
124+
fn from_heap_data(heap_data: HeapRootData) -> Option<Self> {
125+
match heap_data {
126+
HeapRootData::Duration(object) => Some(object),
127+
_ => None,
128+
}
129+
}
130+
}
131+
132+
impl HeapMarkAndSweep for TemporalDuration<'static> {
133+
fn mark_values(&self, queues: &mut WorkQueues) {
134+
queues.durations.push(*self);
135+
}
136+
fn sweep_values(&mut self, compactions: &CompactionLists) {
137+
compactions.durations.shift_index(&mut self.0);
138+
}
139+
}
140+
141+
impl HeapSweepWeakReference for TemporalDuration<'static> {
142+
fn sweep_weak_reference(self, compactions: &CompactionLists) -> Option<Self> {
143+
compactions.durations.shift_weak_index(self.0).map(Self)
144+
}
145+
}
146+
147+
impl<'a> CreateHeapData<DurationHeapData<'a>, TemporalDuration<'a>> for Heap {
148+
fn create(&mut self, data: DurationHeapData<'a>) -> TemporalDuration<'a> {
149+
self.durations.push(data.unbind());
150+
self.alloc_counter += core::mem::size_of::<DurationHeapData<'static>>();
151+
TemporalDuration(BaseIndex::last_t(&self.durations))
152+
}
153+
}
92154
/// 7.5.19 CreateTemporalDuration ( years, months, weeks,
93155
/// days, hours, minutes, seconds,
94156
/// milliseconds, microseconds, nanoseconds [ , newTarget ] )
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use crate::{
2+
ecmascript::{
3+
builders::builtin_function_builder::BuiltinFunctionBuilder,
4+
builtins::{
5+
ArgumentsList, Behaviour, Builtin, BuiltinIntrinsicConstructor
6+
},
7+
execution::{Agent, JsResult, Realm},
8+
types::{BUILTIN_STRING_MEMORY, IntoObject, Object, String, Value},
9+
},
10+
engine::context::{GcScope, NoGcScope},
11+
heap::IntrinsicConstructorIndexes,
12+
};
13+
14+
pub(crate) struct TemporalDurationConstructor;
15+
16+
impl Builtin for TemporalDurationConstructor {
17+
const NAME: String<'static> = BUILTIN_STRING_MEMORY.Duration;
18+
const LENGTH: u8 = 1;
19+
const BEHAVIOUR: Behaviour = Behaviour::Constructor(TemporalDurationConstructor::constructor);
20+
}
21+
impl BuiltinIntrinsicConstructor for TemporalDurationConstructor {
22+
const INDEX: IntrinsicConstructorIndexes = IntrinsicConstructorIndexes::TemporalDuration;
23+
}
24+
25+
impl TemporalDurationConstructor {
26+
fn constructor<'gc>(
27+
_agent: &mut Agent,
28+
_: Value,
29+
_args: ArgumentsList,
30+
_new_target: Option<Object>,
31+
mut _gc: GcScope<'gc, '_>,
32+
) -> JsResult<'gc, Value<'gc>> {
33+
unimplemented!()
34+
}
35+
36+
pub(crate) fn create_intrinsic(agent: &mut Agent, realm: Realm<'static>, _gc: NoGcScope) {
37+
let intrinsics = agent.get_realm_record_by_id(realm).intrinsics();
38+
let duration_prototype = intrinsics.temporal_duration_prototype();
39+
40+
BuiltinFunctionBuilder::new_intrinsic_constructor::<TemporalDurationConstructor>(
41+
agent, realm,
42+
)
43+
.with_property_capacity(5)
44+
.with_prototype_property(duration_prototype.into_object())
45+
.build();
46+
}
47+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use crate::{
2+
ecmascript::{
3+
builders::ordinary_object_builder::OrdinaryObjectBuilder,
4+
execution::{Agent, Realm},
5+
types::BUILTIN_STRING_MEMORY,
6+
},
7+
engine::context::NoGcScope,
8+
heap::WellKnownSymbolIndexes,
9+
};
10+
11+
pub(crate) struct TemporalDurationPrototype;
12+
impl TemporalDurationPrototype {
13+
pub fn create_intrinsic(agent: &mut Agent, realm: Realm<'static>, _: NoGcScope) {
14+
let intrinsics = agent.get_realm_record_by_id(realm).intrinsics();
15+
let this = intrinsics.temporal_instant_prototype();
16+
let object_prototype = intrinsics.object_prototype();
17+
let duration_constructor = intrinsics.temporal_duration();
18+
19+
OrdinaryObjectBuilder::new_intrinsic_object(agent, realm, this)
20+
.with_property_capacity(15)
21+
.with_prototype(object_prototype)
22+
.with_constructor_property(duration_constructor)
23+
.with_property(|builder| {
24+
builder
25+
.with_key(WellKnownSymbolIndexes::ToStringTag.into())
26+
.with_value_readonly(BUILTIN_STRING_MEMORY.Temporal_Duration.into())
27+
.with_enumerable(false)
28+
.with_configurable(true)
29+
.build()
30+
})
31+
.build();
32+
}
33+
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
builtins::{
1717
ordinary::ordinary_create_from_constructor,
1818
temporal::{
19-
duration::{TemporalDuration, create_temporal_duration, to_temporal_duration},
19+
duration::{TemporalDuration, data::DurationHeapData, to_temporal_duration},
2020
error::temporal_err_to_js_err,
2121
get_difference_settings,
2222
options::get_options_object,
@@ -387,7 +387,12 @@ fn difference_temporal_instant<'gc, const IS_UNTIL: bool>(
387387
// 5. Let result be ! TemporalDurationFromInternal(internalDuration, settings.[[LargestUnit]]).
388388
// 6. If operation is since, set result to CreateNegatedTemporsalDuration(result).
389389
// 7. Return result.
390-
create_temporal_duration() // skip CreateNegatedTemporsalDuration and just CreateTemporsalDuration() with result
390+
let result: temporal_rs::Duration = Default::default(); // TODO
391+
// 7. Return result.
392+
Ok(agent.heap.create(DurationHeapData {
393+
object_index: None,
394+
duration: result,
395+
}))
391396
}
392397

393398
#[inline(always)]

0 commit comments

Comments
 (0)