@@ -7,12 +7,13 @@ use crate::engine::NoGcScope;
77use crate :: {
88 ecmascript:: {
99 Agent , ArgumentsList , BUILTIN_STRING_MEMORY , Behaviour , Builtin ,
10- BuiltinIntrinsicConstructor , Error , ExceptionType , Function , JsResult , Object , PropertyKey ,
11- ProtoIntrinsics , Realm , String , Value , builders:: BuiltinFunctionBuilder , get, has_property,
12- ordinary_create_from_constructor, to_string,
10+ BuiltinIntrinsicConstructor , Error , ErrorHeapData , ExceptionType , Function ,
11+ InternalMethods , JsResult , Object , PropertyDescriptor , PropertyKey , ProtoIntrinsics , Realm ,
12+ String , Value , builders:: BuiltinFunctionBuilder , get, has_property,
13+ ordinary_populate_from_constructor, to_string, unwrap_try,
1314 } ,
1415 engine:: { Bindable , GcScope , Scopable } ,
15- heap:: { ArenaAccessMut , IntrinsicConstructorIndexes } ,
16+ heap:: { CreateHeapData , IntrinsicConstructorIndexes } ,
1617} ;
1718
1819pub ( crate ) struct ErrorConstructor ;
@@ -39,74 +40,126 @@ impl Builtin for ErrorIsError {
3940}
4041
4142impl ErrorConstructor {
42- /// ### [20.5.1.1 Error ( message \[ , options \] )](https://tc39.es/ecma262/#sec-error-message )
43- fn constructor < ' gc > (
43+ /// ### [20.5.6. 1.1 NativeError ( message \[ , options \] )](https://tc39.es/ecma262/#sec-nativeerror )
44+ pub ( crate ) fn base_constructor < ' gc > (
4445 agent : & mut Agent ,
45- _this_value : Value ,
46+ error_kind : ExceptionType ,
4647 arguments : ArgumentsList ,
4748 new_target : Option < Object > ,
4849 mut gc : GcScope < ' gc , ' _ > ,
49- ) -> JsResult < ' gc , Value < ' gc > > {
50- let message = arguments. get ( 0 ) . bind ( gc. nogc ( ) ) ;
51- let mut options = arguments. get ( 1 ) . bind ( gc. nogc ( ) ) ;
52- let mut new_target = new_target. bind ( gc. nogc ( ) ) ;
50+ ) -> JsResult < ' gc , Error < ' gc > > {
51+ let nogc = gc. nogc ( ) ;
52+ let scoped_message = arguments. get ( 0 ) . scope ( agent, nogc) ;
53+ let options = arguments. get ( 1 ) . scope ( agent, nogc) ;
54+ let new_target = new_target. bind ( nogc) ;
55+
56+ let intrinsic = match error_kind {
57+ ExceptionType :: Error => ProtoIntrinsics :: Error ,
58+ ExceptionType :: AggregateError => ProtoIntrinsics :: AggregateError ,
59+ ExceptionType :: EvalError => ProtoIntrinsics :: EvalError ,
60+ ExceptionType :: RangeError => ProtoIntrinsics :: RangeError ,
61+ ExceptionType :: ReferenceError => ProtoIntrinsics :: ReferenceError ,
62+ ExceptionType :: SyntaxError => ProtoIntrinsics :: SyntaxError ,
63+ ExceptionType :: TypeError => ProtoIntrinsics :: TypeError ,
64+ ExceptionType :: UriError => ProtoIntrinsics :: URIError ,
65+ } ;
66+
67+ // 1. If NewTarget is undefined, let newTarget be the active function
68+ // object; else let newTarget be NewTarget.
69+ let new_target = new_target. map_or_else (
70+ || agent. running_execution_context ( ) . function . unwrap ( ) ,
71+ |new_target| Function :: try_from ( new_target) . unwrap ( ) ,
72+ ) ;
73+ // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%NativeError.prototype%", « [[ErrorData]] »).
74+ let o = agent
75+ . heap
76+ // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg).
77+ . create ( ErrorHeapData :: new ( error_kind, None , None ) )
78+ . bind ( gc. nogc ( ) ) ;
79+ let o = ordinary_populate_from_constructor (
80+ agent,
81+ o. unbind ( ) . into ( ) ,
82+ new_target. unbind ( ) ,
83+ intrinsic,
84+ gc. reborrow ( ) ,
85+ )
86+ . unbind ( ) ?
87+ . bind ( gc. nogc ( ) ) ;
88+ let mut o = Error :: try_from ( o) . unwrap ( ) ;
89+
90+ // SAFETY: not shared.
91+ let message = unsafe { scoped_message. take ( agent) } . bind ( gc. nogc ( ) ) ;
5392
5493 // 3. If message is not undefined, then
55- let message = if let Ok ( message ) = String :: try_from ( message) {
56- Some ( message . scope ( agent , gc . nogc ( ) ) )
94+ let msg = if let Ok ( msg ) = String :: try_from ( message) {
95+ Some ( msg )
5796 } else if !message. is_undefined ( ) {
97+ let scoped_o = o. scope ( agent, gc. nogc ( ) ) ;
5898 // a. Let msg be ? ToString(message).
59- let scoped_options = options. scope ( agent, gc. nogc ( ) ) ;
60- let scoped_new_target = new_target. map ( |n| n. scope ( agent, gc. nogc ( ) ) ) ;
61- let message = to_string ( agent, message. unbind ( ) , gc. reborrow ( ) )
99+ let ms = to_string ( agent, message. unbind ( ) , gc. reborrow ( ) )
62100 . unbind ( ) ?
63- . scope ( agent, gc. nogc ( ) ) ;
64- // SAFETY: Never shared.
65- unsafe {
66- new_target = scoped_new_target. map ( |n| n. take ( agent) ) . bind ( gc. nogc ( ) ) ;
67- options = scoped_options. take ( agent) . bind ( gc. nogc ( ) ) ;
68- }
69- Some ( message)
101+ . bind ( gc. nogc ( ) ) ;
102+ // SAFETY: not shared.
103+ o = unsafe { scoped_o. take ( agent) } . bind ( gc. nogc ( ) ) ;
104+ Some ( ms)
70105 } else {
71106 None
72107 } ;
108+
109+ // 3. If message is not undefined, then
110+ if let Some ( msg) = msg {
111+ // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg).
112+ unwrap_try ( o. try_define_own_property (
113+ agent,
114+ BUILTIN_STRING_MEMORY . message . into ( ) ,
115+ PropertyDescriptor :: non_enumerable_data_descriptor ( msg) ,
116+ None ,
117+ gc. nogc ( ) ,
118+ ) ) ;
119+ }
120+
121+ // SAFETY: not shared.
122+ let options = unsafe { options. take ( agent) } . bind ( gc. nogc ( ) ) ;
123+
73124 // 4. Perform ? InstallErrorCause(O, options).
74125 let cause = if !options. is_object ( ) {
75126 None
76127 } else {
77- let scoped_new_target = new_target . map ( |n| n . scope ( agent, gc. nogc ( ) ) ) ;
128+ let scoped_o = o . scope ( agent, gc. nogc ( ) ) ;
78129 let cause = get_error_cause ( agent, options. unbind ( ) , gc. reborrow ( ) )
79130 . unbind ( ) ?
80131 . bind ( gc. nogc ( ) ) ;
81- // SAFETY: Never shared.
82- new_target = unsafe { scoped_new_target . map ( |n| n . take ( agent) ) . bind ( gc. nogc ( ) ) } ;
83- cause. map ( |c| c . scope ( agent , gc . nogc ( ) ) )
132+ // SAFETY: not shared.
133+ o = unsafe { scoped_o . take ( agent) } . bind ( gc. nogc ( ) ) ;
134+ cause
84135 } ;
136+ // 1. If options is an Object and ? HasProperty(options, "cause") is
137+ // true, then
138+ if let Some ( cause) = cause {
139+ // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "cause", cause).
140+ unwrap_try ( o. try_define_own_property (
141+ agent,
142+ BUILTIN_STRING_MEMORY . cause . into ( ) ,
143+ PropertyDescriptor :: non_enumerable_data_descriptor ( cause) ,
144+ None ,
145+ gc. nogc ( ) ,
146+ ) ) ;
147+ }
85148
86- // 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
87- let new_target = new_target. map_or_else (
88- || agent. running_execution_context ( ) . function . unwrap ( ) ,
89- |new_target| Function :: try_from ( new_target) . unwrap ( ) ,
90- ) ;
91- // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%Error.prototype%", « [[ErrorData]] »).
92- let o = ordinary_create_from_constructor (
93- agent,
94- new_target. unbind ( ) ,
95- ProtoIntrinsics :: Error ,
96- gc. reborrow ( ) ,
97- )
98- . unbind ( ) ?
99- . bind ( gc. into_nogc ( ) ) ;
100- let o = Error :: try_from ( o) . unwrap ( ) ;
101- // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg).
102- let message = message. map ( |message| message. get ( agent) ) ;
103- let cause = cause. map ( |c| c. get ( agent) ) ;
104- let heap_data = o. get_mut ( agent) ;
105- heap_data. kind = ExceptionType :: Error ;
106- heap_data. message = message;
107- heap_data. cause = cause;
108149 // 5. Return O.
109- Ok ( o. into ( ) )
150+ Ok ( o. unbind ( ) )
151+ }
152+
153+ /// ### [20.5.1.1 Error ( message \[ , options \] )](https://tc39.es/ecma262/#sec-error-message)
154+ fn constructor < ' gc > (
155+ agent : & mut Agent ,
156+ _this_value : Value ,
157+ arguments : ArgumentsList ,
158+ new_target : Option < Object > ,
159+ gc : GcScope < ' gc , ' _ > ,
160+ ) -> JsResult < ' gc , Value < ' gc > > {
161+ Self :: base_constructor ( agent, ExceptionType :: Error , arguments, new_target, gc)
162+ . map ( Value :: from)
110163 }
111164
112165 #[ cfg( feature = "proposal-is-error" ) ]
0 commit comments