1pub mod agent;
12mod array;
13mod atomics;
14mod base64;
15mod bigint;
16mod boolean;
17mod buffer;
18mod case;
19mod collection;
20mod date;
21mod error;
22mod function;
23mod generator;
24mod global;
25mod iterator;
26mod iterator_helpers;
27mod json;
28mod math;
29mod number;
30mod object;
31mod promise;
32mod proxy;
33mod reflect;
34mod regexp;
35mod string;
36mod symbol;
37pub(crate) mod test262;
38mod typed_array;
39mod uri;
40
41use crate::heap::HeapError;
42use crate::heap::object::ObjectKind;
43use crate::heap::string::StringRepr;
44use crate::runtime::{Intrinsic, Names};
45use crate::shape::PropertyFlags;
46use crate::value::{ObjectId, StringId, Value};
47use crate::vm::error::{self as vm_error, ErrorKind};
48use crate::vm::native::CallSite;
49use crate::vm::{Cx, Throw, ops};
50
51pub(crate) type NativeFn = fn(&mut Cx<'_>, CallSite) -> Result<Value, Throw>;
53
54impl Native {
55 pub(crate) const fn frameless(self) -> bool {
59 matches!(
60 self,
61 Native::PromiseResolveFunction
62 | Native::PromiseRejectFunction
63 | Native::PromiseCapabilityExecutor
64 | Native::PromiseThenFinally
65 | Native::PromiseCatchFinally
66 | Native::PromiseValueThunk
67 | Native::PromiseThrower
68 | Native::PromiseAllResolveElement
69 | Native::PromiseAllSettledResolveElement
70 | Native::PromiseAllSettledRejectElement
71 | Native::PromiseAnyRejectElement
72 | Native::ProxyRevoke
73 | Native::AsyncFromSyncUnwrap
74 | Native::AsyncFromSyncCloseRejected
75 | Native::ModuleAsyncRejected
76 | Native::ModuleImportRejected
77 )
78 }
79}
80
81macro_rules! natives {
82 ($($(#[$doc:meta])* $name:ident => $function:path, $js:expr, $length:expr $(, $constructor:ident)?;)*) => {
83 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
85 #[repr(u16)]
86 pub enum Native {
87 $($(#[$doc])* $name,)*
88 }
89
90 impl Native {
91 pub const ALL: &'static [Native] = &[$(Native::$name,)*];
93
94 #[inline]
95 pub(crate) fn function(self) -> NativeFn {
96 match self {
97 $(Native::$name => $function,)*
98 }
99 }
100
101 pub const fn is_constructor(self) -> bool {
103 match self {
104 $(Native::$name => natives!(@constructor $($constructor)?),)*
105 }
106 }
107
108 pub const fn js_name(self) -> &'static str {
110 match self {
111 $(Native::$name => $js,)*
112 }
113 }
114
115 pub const fn length(self) -> u32 {
117 match self {
118 $(Native::$name => $length,)*
119 }
120 }
121 }
122 };
123 (@constructor constructor) => { true };
124 (@constructor) => { false };
125}
126
127natives! {
128 Print => global::print, "print", 1;
131 FunctionCall => function::call, "call", 1;
134 FunctionApply => function::apply, "apply", 2;
136 FunctionPrototype => function::prototype, "", 0;
138 FunctionConstructor => function::constructor, "Function", 1, constructor;
139 FunctionToString => function::to_string, "toString", 0;
140 FunctionBind => function::bind, "bind", 1;
141 FunctionHasInstance => function::has_instance, "[Symbol.hasInstance]", 1;
142 FunctionFileName => function::file_name, "fileName", 0;
143 FunctionLineNumber => function::line_number, "lineNumber", 0;
144 FunctionColumnNumber => function::column_number, "columnNumber", 0;
145 ThrowTypeError => function::throw_type_error, "", 0;
146
147 ParseInt => global::parse_int, "parseInt", 2;
148 ParseFloat => global::parse_float, "parseFloat", 1;
149 Eval => crate::vm::compile::eval, "eval", 1;
150 IsNaN => global::is_nan, "isNaN", 1;
151 IsFinite => global::is_finite, "isFinite", 1;
152
153 ObjectConstructor => object::constructor, "Object", 1, constructor;
154 ObjectToString => object::to_string, "toString", 0;
155 ObjectToLocaleString => object::to_locale_string, "toLocaleString", 0;
156 ObjectValueOf => object::value_of, "valueOf", 0;
157 ObjectHasOwnProperty => object::has_own_property, "hasOwnProperty", 1;
158 ObjectIsPrototypeOf => object::is_prototype_of, "isPrototypeOf", 1;
159 ObjectPropertyIsEnumerable => object::property_is_enumerable, "propertyIsEnumerable", 1;
160 ObjectProtoGetter => object::proto_getter, "__proto__", 0;
161 ObjectProtoSetter => object::proto_setter, "__proto__", 1;
162 ObjectDefineGetter => object::define_getter, "__defineGetter__", 2;
163 ObjectDefineSetter => object::define_setter, "__defineSetter__", 2;
164 ObjectLookupGetter => object::lookup_getter, "__lookupGetter__", 1;
165 ObjectLookupSetter => object::lookup_setter, "__lookupSetter__", 1;
166 ObjectAssign => object::assign, "assign", 2;
167 ObjectCreate => object::create, "create", 2;
168 ObjectDefineProperties => object::define_properties, "defineProperties", 2;
169 ObjectDefineProperty => object::define_property, "defineProperty", 3;
170 ObjectEntries => object::entries, "entries", 1;
171 ObjectFreeze => object::freeze, "freeze", 1;
172 ObjectFromEntries => object::from_entries, "fromEntries", 1;
173 ObjectGetOwnPropertyDescriptor => object::get_own_property_descriptor, "getOwnPropertyDescriptor", 2;
174 ObjectGetOwnPropertyDescriptors => object::get_own_property_descriptors, "getOwnPropertyDescriptors", 1;
175 ObjectGetOwnPropertyNames => object::get_own_property_names, "getOwnPropertyNames", 1;
176 ObjectGetOwnPropertySymbols => object::get_own_property_symbols, "getOwnPropertySymbols", 1;
177 ObjectGetPrototypeOf => object::get_prototype_of, "getPrototypeOf", 1;
178 ObjectGroupBy => object::group_by, "groupBy", 2;
179 ObjectHasOwn => object::has_own, "hasOwn", 2;
180 ObjectIs => object::is, "is", 2;
181 ObjectIsExtensible => object::is_extensible, "isExtensible", 1;
182 ObjectIsFrozen => object::is_frozen, "isFrozen", 1;
183 ObjectIsSealed => object::is_sealed, "isSealed", 1;
184 ObjectKeys => object::keys, "keys", 1;
185 ObjectPreventExtensions => object::prevent_extensions, "preventExtensions", 1;
186 ObjectSeal => object::seal, "seal", 1;
187 ObjectSetPrototypeOf => object::set_prototype_of, "setPrototypeOf", 2;
188 ObjectValues => object::values, "values", 1;
189
190 ReflectApply => reflect::apply, "apply", 3;
191 ReflectConstruct => reflect::construct, "construct", 2;
192 ReflectDefineProperty => reflect::define_property, "defineProperty", 3;
193 ReflectDeleteProperty => reflect::delete_property, "deleteProperty", 2;
194 ReflectGet => reflect::get, "get", 2;
195 ReflectGetOwnPropertyDescriptor => reflect::get_own_property_descriptor, "getOwnPropertyDescriptor", 2;
196 ReflectGetPrototypeOf => reflect::get_prototype_of, "getPrototypeOf", 1;
197 ReflectHas => reflect::has, "has", 2;
198 ReflectIsExtensible => reflect::is_extensible, "isExtensible", 1;
199 ReflectOwnKeys => reflect::own_keys, "ownKeys", 1;
200 ReflectPreventExtensions => reflect::prevent_extensions, "preventExtensions", 1;
201 ReflectSet => reflect::set, "set", 3;
202 ReflectSetPrototypeOf => reflect::set_prototype_of, "setPrototypeOf", 2;
203
204 ProxyConstructor => proxy::constructor, "Proxy", 2, constructor;
205 ProxyRevocable => proxy::revocable, "revocable", 2;
206 ProxyRevoke => proxy::revoke, "", 0;
207
208 SymbolConstructor => symbol::constructor, "Symbol", 0, constructor;
209 SymbolFor => symbol::for_, "for", 1;
210 SymbolKeyFor => symbol::key_for, "keyFor", 1;
211 SymbolToString => symbol::to_string, "toString", 0;
212 SymbolValueOf => symbol::value_of, "valueOf", 0;
213 SymbolDescription => symbol::description, "description", 0;
214 SymbolToPrimitive => symbol::value_of, "[Symbol.toPrimitive]", 1;
215
216 ArrayConstructor => array::constructor, "Array", 1, constructor;
217 ArrayFrom => array::from, "from", 1;
218 ArrayIsArray => array::is_array, "isArray", 1;
219 ArrayOf => array::of, "of", 0;
220 ArrayAt => array::at, "at", 1;
221 ArrayConcat => array::concat, "concat", 1;
222 ArrayCopyWithin => array::copy_within, "copyWithin", 2;
223 ArrayFill => array::fill, "fill", 1;
224 ArrayFind => array::find_, "find", 1;
225 ArrayFindIndex => array::find_index, "findIndex", 1;
226 ArrayFindLast => array::find_last, "findLast", 1;
227 ArrayFindLastIndex => array::find_last_index, "findLastIndex", 1;
228 ArrayLastIndexOf => array::last_index_of, "lastIndexOf", 1;
229 ArrayPop => array::pop, "pop", 0;
230 ArrayPush => array::push, "push", 1;
231 ArrayReverse => array::reverse, "reverse", 0;
232 ArrayShift => array::shift, "shift", 0;
233 ArrayUnshift => array::unshift, "unshift", 1;
234 ArraySlice => array::slice, "slice", 2;
235 ArraySort => array::sort, "sort", 1;
236 ArraySplice => array::splice, "splice", 2;
237 ArrayIncludes => array::includes, "includes", 1;
238 ArrayIndexOf => array::index_of, "indexOf", 1;
239 ArrayJoin => array::join, "join", 1;
240 ArrayToString => array::to_string, "toString", 0;
241 ArrayToLocaleString => array::to_locale_string, "toLocaleString", 0;
242 ArrayEvery => array::every, "every", 1;
243 ArraySome => array::some, "some", 1;
244 ArrayForEach => array::for_each, "forEach", 1;
245 ArrayMap => array::map, "map", 1;
246 ArrayFilter => array::filter, "filter", 1;
247 ArrayReduce => array::reduce, "reduce", 1;
248 ArrayReduceRight => array::reduce_right, "reduceRight", 1;
249 ArrayFlat => array::flat, "flat", 0;
250 ArrayFlatMap => array::flat_map, "flatMap", 1;
251 ArrayToReversed => array::to_reversed, "toReversed", 0;
252 ArrayToSorted => array::to_sorted, "toSorted", 1;
253 ArrayToSpliced => array::to_spliced, "toSpliced", 2;
254 ArrayWith => array::with, "with", 2;
255 ArrayValues => iterator::values, "values", 0;
256 ArrayKeys => iterator::keys, "keys", 0;
257 ArrayEntries => iterator::entries, "entries", 0;
258 ArrayIteratorNext => iterator::array_iterator_next, "next", 0;
259 IteratorPrototypeIterator => iterator::iterator_prototype_iterator, "[Symbol.iterator]", 0;
260 StringIterator => iterator::string_iterator, "[Symbol.iterator]", 0;
261 StringIteratorNext => iterator::string_iterator_next, "next", 0;
262
263 StringConstructor => string::constructor, "String", 1, constructor;
264 StringFromCharCode => string::from_char_code, "fromCharCode", 1;
265 StringFromCodePoint => string::from_code_point, "fromCodePoint", 1;
266 StringRaw => string::raw, "raw", 1;
267 StringAt => string::at, "at", 1;
268 StringCharAt => string::char_at, "charAt", 1;
269 StringCharCodeAt => string::char_code_at, "charCodeAt", 1;
270 StringCodePointAt => string::code_point_at, "codePointAt", 1;
271 StringConcat => string::concat, "concat", 1;
272 StringEndsWith => string::ends_with, "endsWith", 1;
273 StringIncludes => string::includes, "includes", 1;
274 StringIndexOf => string::index_of, "indexOf", 1;
275 StringIsWellFormed => string::is_well_formed, "isWellFormed", 0;
276 StringLastIndexOf => string::last_index_of, "lastIndexOf", 1;
277 StringLocaleCompare => string::locale_compare, "localeCompare", 1;
278 StringMatch => string::match_, "match", 1;
279 StringMatchAll => string::match_all, "matchAll", 1;
280 StringNormalize => string::normalize, "normalize", 0;
281 StringPadEnd => string::pad_end, "padEnd", 1;
282 StringPadStart => string::pad_start, "padStart", 1;
283 StringRepeat => string::repeat, "repeat", 1;
284 StringReplace => string::replace, "replace", 2;
285 StringReplaceAll => string::replace_all, "replaceAll", 2;
286 StringSearch => string::search, "search", 1;
287 StringSlice => string::slice, "slice", 2;
288 StringSplit => string::split, "split", 2;
289 StringStartsWith => string::starts_with, "startsWith", 1;
290 StringSubstr => string::substr, "substr", 2;
291 StringSubstring => string::substring, "substring", 2;
292 StringToLocaleLowerCase => string::to_lower_case, "toLocaleLowerCase", 0;
293 StringToLocaleUpperCase => string::to_upper_case, "toLocaleUpperCase", 0;
294 StringToLowerCase => string::to_lower_case, "toLowerCase", 0;
295 StringToString => string::value_of, "toString", 0;
296 StringToUpperCase => string::to_upper_case, "toUpperCase", 0;
297 StringToWellFormed => string::to_well_formed, "toWellFormed", 0;
298 StringTrim => string::trim, "trim", 0;
299 StringTrimEnd => string::trim_end, "trimEnd", 0;
300 StringTrimStart => string::trim_start, "trimStart", 0;
301 StringValueOf => string::value_of, "valueOf", 0;
302 StringAnchor => string::anchor, "anchor", 1;
303 StringBig => string::big, "big", 0;
304 StringBlink => string::blink, "blink", 0;
305 StringBold => string::bold, "bold", 0;
306 StringFixed => string::fixed, "fixed", 0;
307 StringFontcolor => string::fontcolor, "fontcolor", 1;
308 StringFontsize => string::fontsize, "fontsize", 1;
309 StringItalics => string::italics, "italics", 0;
310 StringLink => string::link, "link", 1;
311 StringSmall => string::small, "small", 0;
312 StringStrike => string::strike, "strike", 0;
313 StringSub => string::sub, "sub", 0;
314 StringSup => string::sup, "sup", 0;
315
316 NumberConstructor => number::constructor, "Number", 1, constructor;
317 NumberToString => number::to_string, "toString", 1;
318 NumberToLocaleString => number::to_locale_string, "toLocaleString", 0;
319 NumberValueOf => number::value_of, "valueOf", 0;
320 NumberToFixed => number::to_fixed, "toFixed", 1;
321 NumberToExponential => number::to_exponential, "toExponential", 1;
322 NumberToPrecision => number::to_precision, "toPrecision", 1;
323 NumberIsFinite => number::is_finite, "isFinite", 1;
324 NumberIsInteger => number::is_integer, "isInteger", 1;
325 NumberIsNaN => number::is_nan, "isNaN", 1;
326 NumberIsSafeInteger => number::is_safe_integer, "isSafeInteger", 1;
327
328 BooleanConstructor => boolean::constructor, "Boolean", 1, constructor;
329 BooleanToString => boolean::to_string, "toString", 0;
330 BooleanValueOf => boolean::value_of, "valueOf", 0;
331
332 BigIntConstructor => bigint::constructor, "BigInt", 1, constructor;
333 BigIntAsIntN => bigint::as_int_n, "asIntN", 2;
334 BigIntAsUintN => bigint::as_uint_n, "asUintN", 2;
335 BigIntToLocaleString => bigint::to_locale_string, "toLocaleString", 0;
336 BigIntToString => bigint::to_string, "toString", 0;
337 BigIntValueOf => bigint::value_of, "valueOf", 0;
338
339 DecodeUri => uri::decode_uri, "decodeURI", 1;
340 DecodeUriComponent => uri::decode_uri_component, "decodeURIComponent", 1;
341 EncodeUri => uri::encode_uri, "encodeURI", 1;
342 EncodeUriComponent => uri::encode_uri_component, "encodeURIComponent", 1;
343 Escape => uri::escape, "escape", 1;
344 Unescape => uri::unescape, "unescape", 1;
345
346 MathAbs => math::abs, "abs", 1;
347 MathAcos => math::acos, "acos", 1;
348 MathAcosh => math::acosh, "acosh", 1;
349 MathAsin => math::asin, "asin", 1;
350 MathAsinh => math::asinh, "asinh", 1;
351 MathAtan => math::atan, "atan", 1;
352 MathAtanh => math::atanh, "atanh", 1;
353 MathAtan2 => math::atan2, "atan2", 2;
354 MathCbrt => math::cbrt, "cbrt", 1;
355 MathCeil => math::ceil, "ceil", 1;
356 MathClz32 => math::clz32, "clz32", 1;
357 MathCos => math::cos, "cos", 1;
358 MathCosh => math::cosh, "cosh", 1;
359 MathExp => math::exp, "exp", 1;
360 MathExpm1 => math::expm1, "expm1", 1;
361 MathFloor => math::floor, "floor", 1;
362 MathFround => math::fround, "fround", 1;
363 MathF16round => math::f16round, "f16round", 1;
364 MathHypot => math::hypot, "hypot", 2;
365 MathImul => math::imul, "imul", 2;
366 MathLog => math::log, "log", 1;
367 MathLog1p => math::log1p, "log1p", 1;
368 MathLog10 => math::log10, "log10", 1;
369 MathLog2 => math::log2, "log2", 1;
370 MathMax => math::max, "max", 2;
371 MathMin => math::min, "min", 2;
372 MathPow => math::pow, "pow", 2;
373 MathRandom => math::random, "random", 0;
374 MathRound => math::round, "round", 1;
375 MathSign => math::sign, "sign", 1;
376 MathSin => math::sin, "sin", 1;
377 MathSinh => math::sinh, "sinh", 1;
378 MathSqrt => math::sqrt, "sqrt", 1;
379 MathSumPrecise => math::sum_precise, "sumPrecise", 1;
380 MathTan => math::tan, "tan", 1;
381 MathTanh => math::tanh, "tanh", 1;
382 MathTrunc => math::trunc, "trunc", 1;
383
384 RegExpConstructor => regexp::constructor, "RegExp", 2, constructor;
385 RegExpEscape => regexp::escape, "escape", 1;
386 RegExpCompile => regexp::compile, "compile", 2;
387 RegExpExec => regexp::exec, "exec", 1;
388 RegExpTest => regexp::test, "test", 1;
389 RegExpToString => regexp::to_string, "toString", 0;
390 RegExpSource => regexp::source, "source", 0;
391 RegExpFlags => regexp::flags, "flags", 0;
392 RegExpHasIndices => regexp::has_indices, "hasIndices", 0;
393 RegExpGlobal => regexp::global, "global", 0;
394 RegExpIgnoreCase => regexp::ignore_case, "ignoreCase", 0;
395 RegExpMultiline => regexp::multiline, "multiline", 0;
396 RegExpDotAll => regexp::dot_all, "dotAll", 0;
397 RegExpUnicode => regexp::unicode, "unicode", 0;
398 RegExpUnicodeSets => regexp::unicode_sets, "unicodeSets", 0;
399 RegExpSticky => regexp::sticky, "sticky", 0;
400 RegExpSymbolMatch => regexp::symbol_match, "[Symbol.match]", 1;
401 RegExpSymbolMatchAll => regexp::symbol_match_all, "[Symbol.matchAll]", 1;
402 RegExpSymbolReplace => regexp::symbol_replace, "[Symbol.replace]", 2;
403 RegExpSymbolSearch => regexp::symbol_search, "[Symbol.search]", 1;
404 RegExpSymbolSplit => regexp::symbol_split, "[Symbol.split]", 2;
405 RegExpStringIteratorNext => regexp::string_iterator_next, "next", 0;
406
407 ErrorConstructor => error::error, "Error", 1, constructor;
408 EvalErrorConstructor => error::eval_error, "EvalError", 1, constructor;
409 RangeErrorConstructor => error::range_error, "RangeError", 1, constructor;
410 ReferenceErrorConstructor => error::reference_error, "ReferenceError", 1, constructor;
411 SyntaxErrorConstructor => error::syntax_error, "SyntaxError", 1, constructor;
412 TypeErrorConstructor => error::type_error, "TypeError", 1, constructor;
413 InternalErrorConstructor => error::internal_error, "InternalError", 1, constructor;
414 UriErrorConstructor => error::uri_error, "URIError", 1, constructor;
415 AggregateErrorConstructor => error::aggregate_error, "AggregateError", 2, constructor;
416 ErrorToString => error::to_string, "toString", 0;
417 ErrorIsError => error::is_error, "isError", 1;
418
419 PromiseConstructor => promise::constructor, "Promise", 1, constructor;
420 PromiseResolveFunction => promise::resolve_function, "", 1;
421 PromiseRejectFunction => promise::reject_function, "", 1;
422 PromiseCapabilityExecutor => promise::capability_executor, "", 2;
423 PromiseThen => promise::then, "then", 2;
424 PromiseCatch => promise::catch, "catch", 1;
425 PromiseFinally => promise::finally, "finally", 1;
426 PromiseThenFinally => promise::then_finally, "", 1;
427 PromiseCatchFinally => promise::catch_finally, "", 1;
428 PromiseValueThunk => promise::value_thunk, "", 0;
429 PromiseThrower => promise::thrower, "", 0;
430 PromiseResolveStatic => promise::resolve_static, "resolve", 1;
431 PromiseRejectStatic => promise::reject_static, "reject", 1;
432 PromiseWithResolvers => promise::with_resolvers, "withResolvers", 0;
433 PromiseTry => promise::try_, "try", 1;
434 PromiseAll => promise::all, "all", 1;
435 PromiseAllSettled => promise::all_settled, "allSettled", 1;
436 PromiseAny => promise::any, "any", 1;
437 PromiseRace => promise::race, "race", 1;
438 PromiseAllResolveElement => promise::all_resolve_element, "", 1;
439 PromiseAllSettledResolveElement => promise::all_settled_resolve_element, "", 1;
440 PromiseAllSettledRejectElement => promise::all_settled_reject_element, "", 1;
441 PromiseAnyRejectElement => promise::any_reject_element, "", 1;
442 SpeciesGetter => promise::species_getter, "[Symbol.species]", 0;
443
444 GeneratorFunctionConstructor => generator::generator_function_constructor, "GeneratorFunction", 1, constructor;
445 AsyncFunctionConstructor => generator::async_function_constructor, "AsyncFunction", 1, constructor;
446 AsyncGeneratorFunctionConstructor => generator::async_generator_function_constructor, "AsyncGeneratorFunction", 1, constructor;
447 GeneratorNext => generator::next, "next", 1;
448 GeneratorReturn => generator::return_, "return", 1;
449 GeneratorThrow => generator::throw, "throw", 1;
450 AsyncIteratorPrototypeAsyncIterator => generator::async_iterator_prototype_async_iterator, "[Symbol.asyncIterator]", 0;
451 AsyncFromSyncNext => generator::async_from_sync_next, "next", 1;
452 AsyncFromSyncReturn => generator::async_from_sync_return, "return", 1;
453 AsyncFromSyncThrow => generator::async_from_sync_throw, "throw", 1;
454 AsyncFromSyncUnwrap => generator::async_from_sync_unwrap, "", 1;
455 AsyncFromSyncCloseRejected => generator::async_from_sync_close_rejected, "", 1;
456 AsyncGeneratorNext => crate::vm::async_generator::next, "next", 1;
457 AsyncGeneratorReturn => crate::vm::async_generator::return_, "return", 1;
458 AsyncGeneratorThrow => crate::vm::async_generator::throw, "throw", 1;
459
460 DateConstructor => date::constructor, "Date", 7, constructor;
461 DateNow => date::now_, "now", 0;
462 DateParse => date::parse, "parse", 1;
463 DateUtc => date::utc, "UTC", 7;
464 DateValueOf => date::value_of, "valueOf", 0;
465 DateGetTime => date::value_of, "getTime", 0;
466 DateToString => date::to_string, "toString", 0;
467 DateToDateString => date::to_date_string, "toDateString", 0;
468 DateToTimeString => date::to_time_string, "toTimeString", 0;
469 DateToUtcString => date::to_utc_string, "toUTCString", 0;
470 DateToIsoString => date::to_iso_string, "toISOString", 0;
471 DateToLocaleString => date::to_locale_string, "toLocaleString", 0;
472 DateToLocaleDateString => date::to_locale_date_string, "toLocaleDateString", 0;
473 DateToLocaleTimeString => date::to_locale_time_string, "toLocaleTimeString", 0;
474 DateToPrimitive => date::to_primitive, "[Symbol.toPrimitive]", 1;
475 DateGetTimezoneOffset => date::get_timezone_offset, "getTimezoneOffset", 0;
476 DateGetYear => date::get_year, "getYear", 0;
477 DateGetFullYear => date::get_full_year, "getFullYear", 0;
478 DateGetUtcFullYear => date::get_utc_full_year, "getUTCFullYear", 0;
479 DateGetMonth => date::get_month, "getMonth", 0;
480 DateGetUtcMonth => date::get_utc_month, "getUTCMonth", 0;
481 DateGetDate => date::get_date, "getDate", 0;
482 DateGetUtcDate => date::get_utc_date, "getUTCDate", 0;
483 DateGetHours => date::get_hours, "getHours", 0;
484 DateGetUtcHours => date::get_utc_hours, "getUTCHours", 0;
485 DateGetMinutes => date::get_minutes, "getMinutes", 0;
486 DateGetUtcMinutes => date::get_utc_minutes, "getUTCMinutes", 0;
487 DateGetSeconds => date::get_seconds, "getSeconds", 0;
488 DateGetUtcSeconds => date::get_utc_seconds, "getUTCSeconds", 0;
489 DateGetMilliseconds => date::get_milliseconds, "getMilliseconds", 0;
490 DateGetUtcMilliseconds => date::get_utc_milliseconds, "getUTCMilliseconds", 0;
491 DateGetDay => date::get_day, "getDay", 0;
492 DateGetUtcDay => date::get_utc_day, "getUTCDay", 0;
493 DateSetMilliseconds => date::set_milliseconds, "setMilliseconds", 1;
494 DateSetUtcMilliseconds => date::set_utc_milliseconds, "setUTCMilliseconds", 1;
495 DateSetSeconds => date::set_seconds, "setSeconds", 2;
496 DateSetUtcSeconds => date::set_utc_seconds, "setUTCSeconds", 2;
497 DateSetMinutes => date::set_minutes, "setMinutes", 3;
498 DateSetUtcMinutes => date::set_utc_minutes, "setUTCMinutes", 3;
499 DateSetHours => date::set_hours, "setHours", 4;
500 DateSetUtcHours => date::set_utc_hours, "setUTCHours", 4;
501 DateSetDate => date::set_date, "setDate", 1;
502 DateSetUtcDate => date::set_utc_date, "setUTCDate", 1;
503 DateSetMonth => date::set_month, "setMonth", 2;
504 DateSetUtcMonth => date::set_utc_month, "setUTCMonth", 2;
505 DateSetFullYear => date::set_full_year, "setFullYear", 3;
506 DateSetUtcFullYear => date::set_utc_full_year, "setUTCFullYear", 3;
507 DateSetTime => date::set_time, "setTime", 1;
508 DateSetYear => date::set_year, "setYear", 1;
509 DateToJson => date::to_json, "toJSON", 1;
510
511 JsonIsRawJson => json::is_raw_json, "isRawJSON", 1;
512 JsonParse => json::parse, "parse", 2;
513 JsonRawJson => json::raw_json, "rawJSON", 1;
514 JsonStringify => json::stringify, "stringify", 3;
515
516 MapConstructor => collection::map_constructor, "Map", 0, constructor;
517 MapGroupBy => collection::group_by, "groupBy", 2;
518 MapSet => collection::map_set, "set", 2;
519 MapGet => collection::map_get, "get", 1;
520 MapGetOrInsert => collection::map_get_or_insert, "getOrInsert", 2;
521 MapGetOrInsertComputed => collection::map_get_or_insert_computed, "getOrInsertComputed", 2;
522 MapHas => collection::map_has, "has", 1;
523 MapDelete => collection::map_delete, "delete", 1;
524 MapClear => collection::map_clear, "clear", 0;
525 MapSize => collection::map_size, "size", 0;
526 MapForEach => collection::map_for_each, "forEach", 1;
527 MapValues => collection::map_values, "values", 0;
528 MapKeys => collection::map_keys, "keys", 0;
529 MapEntries => collection::map_entries, "entries", 0;
530 MapIteratorNext => collection::map_iterator_next, "next", 0;
531 SetConstructor => collection::set_constructor, "Set", 0, constructor;
532 SetAdd => collection::set_add, "add", 1;
533 SetHas => collection::set_has, "has", 1;
534 SetDelete => collection::set_delete, "delete", 1;
535 SetClear => collection::set_clear, "clear", 0;
536 SetSize => collection::set_size, "size", 0;
537 SetForEach => collection::set_for_each, "forEach", 1;
538 SetIsDisjointFrom => collection::set_is_disjoint_from, "isDisjointFrom", 1;
539 SetIsSubsetOf => collection::set_is_subset_of, "isSubsetOf", 1;
540 SetIsSupersetOf => collection::set_is_superset_of, "isSupersetOf", 1;
541 SetIntersection => collection::set_intersection, "intersection", 1;
542 SetDifference => collection::set_difference, "difference", 1;
543 SetSymmetricDifference => collection::set_symmetric_difference, "symmetricDifference", 1;
544 SetUnion => collection::set_union, "union", 1;
545 SetValues => collection::set_values, "values", 0;
546 SetEntries => collection::set_entries, "entries", 0;
547 SetIteratorNext => collection::set_iterator_next, "next", 0;
548 WeakMapConstructor => collection::weak_map_constructor, "WeakMap", 0, constructor;
549 WeakMapSet => collection::weak_map_set, "set", 2;
550 WeakMapGet => collection::weak_map_get, "get", 1;
551 WeakMapGetOrInsert => collection::weak_map_get_or_insert, "getOrInsert", 2;
552 WeakMapGetOrInsertComputed => collection::weak_map_get_or_insert_computed, "getOrInsertComputed", 2;
553 WeakMapHas => collection::weak_map_has, "has", 1;
554 WeakMapDelete => collection::weak_map_delete, "delete", 1;
555 WeakSetConstructor => collection::weak_set_constructor, "WeakSet", 0, constructor;
556 WeakSetAdd => collection::weak_set_add, "add", 1;
557 WeakSetHas => collection::weak_set_has, "has", 1;
558 WeakSetDelete => collection::weak_set_delete, "delete", 1;
559 WeakRefConstructor => collection::weak_ref_constructor, "WeakRef", 1, constructor;
560 WeakRefDeref => collection::weak_ref_deref, "deref", 0;
561 FinalizationRegistryConstructor => collection::finalization_registry_constructor, "FinalizationRegistry", 1, constructor;
562 FinalizationRegistryRegister => collection::finalization_registry_register, "register", 2;
563 FinalizationRegistryUnregister => collection::finalization_registry_unregister, "unregister", 1;
564
565 IteratorConstructor => iterator_helpers::constructor, "Iterator", 0, constructor;
566 IteratorConstructorGetter => iterator_helpers::constructor_getter, "constructor", 0;
567 IteratorConstructorSetter => iterator_helpers::constructor_setter, "constructor", 1;
568 IteratorToStringTagGetter => iterator_helpers::to_string_tag_getter, "[Symbol.toStringTag]", 0;
569 IteratorToStringTagSetter => iterator_helpers::to_string_tag_setter, "[Symbol.toStringTag]", 1;
570 IteratorFrom => iterator_helpers::from, "from", 1;
571 IteratorConcat => iterator_helpers::concat, "concat", 0;
572 WrapForValidNext => iterator_helpers::wrap_next, "next", 0;
573 WrapForValidReturn => iterator_helpers::wrap_return, "return", 0;
574 IteratorDrop => iterator_helpers::drop, "drop", 1;
575 IteratorFilter => iterator_helpers::filter, "filter", 1;
576 IteratorFlatMap => iterator_helpers::flat_map, "flatMap", 1;
577 IteratorMap => iterator_helpers::map, "map", 1;
578 IteratorTake => iterator_helpers::take, "take", 1;
579 IteratorEvery => iterator_helpers::every, "every", 1;
580 IteratorFind => iterator_helpers::find, "find", 1;
581 IteratorForEach => iterator_helpers::for_each, "forEach", 1;
582 IteratorSome => iterator_helpers::some, "some", 1;
583 IteratorReduce => iterator_helpers::reduce, "reduce", 1;
584 IteratorToArray => iterator_helpers::to_array, "toArray", 0;
585 IteratorHelperNext => iterator_helpers::helper_next, "next", 0;
586 IteratorHelperReturn => iterator_helpers::helper_return, "return", 0;
587
588 ArrayBufferConstructor => buffer::array_buffer_constructor, "ArrayBuffer", 1, constructor;
589 ArrayBufferIsView => buffer::is_view, "isView", 1;
590 ArrayBufferByteLength => buffer::byte_length, "byteLength", 0;
591 ArrayBufferMaxByteLength => buffer::max_byte_length, "maxByteLength", 0;
592 ArrayBufferResizable => buffer::resizable, "resizable", 0;
593 ArrayBufferDetached => buffer::detached, "detached", 0;
594 ArrayBufferResize => buffer::resize, "resize", 1;
595 ArrayBufferSlice => buffer::slice, "slice", 2;
596 ArrayBufferTransfer => buffer::transfer, "transfer", 0;
597 ArrayBufferTransferToFixedLength => buffer::transfer_to_fixed_length, "transferToFixedLength", 0;
598 SharedArrayBufferConstructor => buffer::shared_array_buffer_constructor, "SharedArrayBuffer", 1, constructor;
599 SharedArrayBufferByteLength => buffer::shared_byte_length, "byteLength", 0;
600 SharedArrayBufferGrowable => buffer::growable, "growable", 0;
601 SharedArrayBufferMaxByteLength => buffer::shared_max_byte_length, "maxByteLength", 0;
602 SharedArrayBufferGrow => buffer::grow, "grow", 1;
603 SharedArrayBufferSlice => buffer::shared_slice, "slice", 2;
604 DataViewConstructor => buffer::data_view_constructor, "DataView", 1, constructor;
605 DataViewBuffer => buffer::data_view_buffer, "buffer", 0;
606 DataViewByteLength => buffer::data_view_byte_length, "byteLength", 0;
607 DataViewByteOffset => buffer::data_view_byte_offset, "byteOffset", 0;
608 DataViewGetInt8 => buffer::get_int8, "getInt8", 1;
609 DataViewSetInt8 => buffer::set_int8, "setInt8", 2;
610 DataViewGetUint8 => buffer::get_uint8, "getUint8", 1;
611 DataViewSetUint8 => buffer::set_uint8, "setUint8", 2;
612 DataViewGetInt16 => buffer::get_int16, "getInt16", 1;
613 DataViewSetInt16 => buffer::set_int16, "setInt16", 2;
614 DataViewGetUint16 => buffer::get_uint16, "getUint16", 1;
615 DataViewSetUint16 => buffer::set_uint16, "setUint16", 2;
616 DataViewGetInt32 => buffer::get_int32, "getInt32", 1;
617 DataViewSetInt32 => buffer::set_int32, "setInt32", 2;
618 DataViewGetUint32 => buffer::get_uint32, "getUint32", 1;
619 DataViewSetUint32 => buffer::set_uint32, "setUint32", 2;
620 DataViewGetFloat16 => buffer::get_float16, "getFloat16", 1;
621 DataViewSetFloat16 => buffer::set_float16, "setFloat16", 2;
622 DataViewGetFloat32 => buffer::get_float32, "getFloat32", 1;
623 DataViewSetFloat32 => buffer::set_float32, "setFloat32", 2;
624 DataViewGetFloat64 => buffer::get_float64, "getFloat64", 1;
625 DataViewSetFloat64 => buffer::set_float64, "setFloat64", 2;
626 DataViewGetBigInt64 => buffer::get_big_int64, "getBigInt64", 1;
627 DataViewSetBigInt64 => buffer::set_big_int64, "setBigInt64", 2;
628 DataViewGetBigUint64 => buffer::get_big_uint64, "getBigUint64", 1;
629 DataViewSetBigUint64 => buffer::set_big_uint64, "setBigUint64", 2;
630 TypedArrayConstructor => typed_array::abstract_constructor, "TypedArray", 0, constructor;
631 TypedArrayFrom => typed_array::from, "from", 1;
632 TypedArrayOf => typed_array::of, "of", 0;
633 TypedArrayBuffer => typed_array::buffer_getter, "buffer", 0;
634 TypedArrayByteLength => typed_array::byte_length, "byteLength", 0;
635 TypedArrayByteOffset => typed_array::byte_offset, "byteOffset", 0;
636 TypedArrayLength => typed_array::length, "length", 0;
637 TypedArrayToStringTag => typed_array::to_string_tag_getter, "[Symbol.toStringTag]", 0;
638 TypedArrayAt => typed_array::at, "at", 1;
639 TypedArrayCopyWithin => typed_array::copy_within, "copyWithin", 2;
640 TypedArrayEntries => typed_array::entries, "entries", 0;
641 TypedArrayEvery => typed_array::every, "every", 1;
642 TypedArrayFill => typed_array::fill, "fill", 1;
643 TypedArrayFilter => typed_array::filter, "filter", 1;
644 TypedArrayFind => typed_array::find, "find", 1;
645 TypedArrayFindIndex => typed_array::find_index, "findIndex", 1;
646 TypedArrayFindLast => typed_array::find_last, "findLast", 1;
647 TypedArrayFindLastIndex => typed_array::find_last_index, "findLastIndex", 1;
648 TypedArrayForEach => typed_array::for_each, "forEach", 1;
649 TypedArrayIncludes => typed_array::includes, "includes", 1;
650 TypedArrayIndexOf => typed_array::index_of, "indexOf", 1;
651 TypedArrayJoin => typed_array::join, "join", 1;
652 TypedArrayKeys => typed_array::keys, "keys", 0;
653 TypedArrayLastIndexOf => typed_array::last_index_of, "lastIndexOf", 1;
654 TypedArrayMap => typed_array::map, "map", 1;
655 TypedArrayReduce => typed_array::reduce, "reduce", 1;
656 TypedArrayReduceRight => typed_array::reduce_right, "reduceRight", 1;
657 TypedArrayReverse => typed_array::reverse, "reverse", 0;
658 TypedArraySet => typed_array::set_method, "set", 1;
659 TypedArraySlice => typed_array::slice, "slice", 2;
660 TypedArraySome => typed_array::some, "some", 1;
661 TypedArraySort => typed_array::sort, "sort", 1;
662 TypedArraySubarray => typed_array::subarray, "subarray", 2;
663 TypedArrayToLocaleString => typed_array::to_locale_string, "toLocaleString", 0;
664 TypedArrayToReversed => typed_array::to_reversed, "toReversed", 0;
665 TypedArrayToSorted => typed_array::to_sorted, "toSorted", 1;
666 TypedArrayValues => typed_array::values, "values", 0;
667 TypedArrayWith => typed_array::with, "with", 2;
668 Int8ArrayConstructor => typed_array::int8_array, "Int8Array", 3, constructor;
669 Uint8ArrayConstructor => typed_array::uint8_array, "Uint8Array", 3, constructor;
670 Uint8ClampedArrayConstructor => typed_array::uint8_clamped_array, "Uint8ClampedArray", 3, constructor;
671 Int16ArrayConstructor => typed_array::int16_array, "Int16Array", 3, constructor;
672 Uint16ArrayConstructor => typed_array::uint16_array, "Uint16Array", 3, constructor;
673 Int32ArrayConstructor => typed_array::int32_array, "Int32Array", 3, constructor;
674 Uint32ArrayConstructor => typed_array::uint32_array, "Uint32Array", 3, constructor;
675 Float16ArrayConstructor => typed_array::float16_array, "Float16Array", 3, constructor;
676 Float32ArrayConstructor => typed_array::float32_array, "Float32Array", 3, constructor;
677 Float64ArrayConstructor => typed_array::float64_array, "Float64Array", 3, constructor;
678 BigInt64ArrayConstructor => typed_array::big_int64_array, "BigInt64Array", 3, constructor;
679 BigUint64ArrayConstructor => typed_array::big_uint64_array, "BigUint64Array", 3, constructor;
680 Uint8ArrayFromBase64 => typed_array::from_base64, "fromBase64", 1;
681 Uint8ArrayFromHex => typed_array::from_hex, "fromHex", 1;
682 Uint8ArrayToBase64 => typed_array::to_base64, "toBase64", 0;
683 Uint8ArraySetFromBase64 => typed_array::set_from_base64, "setFromBase64", 1;
684 Uint8ArrayToHex => typed_array::to_hex, "toHex", 0;
685 Uint8ArraySetFromHex => typed_array::set_from_hex, "setFromHex", 1;
686 AtomicsAdd => atomics::add, "add", 3;
687 AtomicsAnd => atomics::and, "and", 3;
688 AtomicsCompareExchange => atomics::compare_exchange, "compareExchange", 4;
689 AtomicsExchange => atomics::exchange, "exchange", 3;
690 AtomicsIsLockFree => atomics::is_lock_free, "isLockFree", 1;
691 AtomicsLoad => atomics::load, "load", 2;
692 AtomicsNotify => atomics::notify, "notify", 3;
693 AtomicsOr => atomics::or, "or", 3;
694 AtomicsStore => atomics::store, "store", 3;
695 AtomicsSub => atomics::sub, "sub", 3;
696 AtomicsWait => atomics::wait, "wait", 4;
697 AtomicsXor => atomics::xor, "xor", 3;
698 AtomicsPause => atomics::pause, "pause", 0;
699
700 AgentStart => agent::start, "start", 1;
701 AgentBroadcast => agent::broadcast, "broadcast", 2;
702 AgentGetReport => agent::get_report, "getReport", 0;
703 AgentSleep => agent::sleep, "sleep", 1;
704 AgentMonotonicNow => agent::monotonic_now, "monotonicNow", 0;
705 AgentReceiveBroadcast => agent::receive_broadcast, "receiveBroadcast", 1;
706 AgentReport => agent::report, "report", 1;
707 AgentLeaving => agent::leaving, "leaving", 0;
708
709 ModuleAsyncFulfilled => crate::vm::module::module_async_fulfilled, "", 1;
710 ModuleAsyncRejected => crate::vm::module::module_async_rejected, "", 1;
711 ModuleImportFulfilled => crate::vm::module::module_import_fulfilled, "", 1;
712 ModuleImportJob => crate::vm::module::module_import_job, "", 0;
713 ModuleImportRejected => crate::vm::module::module_import_rejected, "", 1;
714
715 Test262CreateRealm => test262::create_realm, "createRealm", 0;
716 Test262Gc => test262::gc, "gc", 0;
717 Test262EvalScript => test262::eval_script, "evalScript", 1;
718 Test262DetachArrayBuffer => test262::detach_array_buffer, "detachArrayBuffer", 1;
719 Test262CodePointRange => test262::code_point_range, "codePointRange", 2;
720
721 ConsoleLog => global::print, "log", 1;
722 Load => crate::vm::compile::load, "load", 1;
723 Read => crate::vm::compile::read, "read", 1;
724 LoadScript => crate::vm::compile::load_script, "__loadScript", 1;
725 PerformanceNow => global::performance_now, "now", 0;
726
727 HostFunction => crate::vm::native::host_call, "", 0;
730 HostConstructor => crate::vm::native::host_call, "", 0, constructor;
732}
733
734impl Native {
735 #[inline]
736 pub(crate) const fn index(self) -> u32 {
737 self as u32
738 }
739
740 #[inline]
741 pub(crate) fn from_index(index: u32) -> Option<Native> {
742 Native::ALL.get(index as usize).copied()
743 }
744
745 pub(crate) const fn error(kind: ErrorKind) -> Native {
747 match kind {
748 ErrorKind::Error => Native::ErrorConstructor,
749 ErrorKind::Eval => Native::EvalErrorConstructor,
750 ErrorKind::Range => Native::RangeErrorConstructor,
751 ErrorKind::Reference => Native::ReferenceErrorConstructor,
752 ErrorKind::Syntax => Native::SyntaxErrorConstructor,
753 ErrorKind::Type => Native::TypeErrorConstructor,
754 ErrorKind::Internal => Native::InternalErrorConstructor,
755 ErrorKind::Uri => Native::UriErrorConstructor,
756 ErrorKind::Aggregate => Native::AggregateErrorConstructor,
757 }
758 }
759}
760
761pub(crate) fn relative(index: f64, length: usize) -> usize {
766 let length = length as f64;
767 let index = if index < 0.0 {
768 (length + index).max(0.0)
769 } else {
770 index.min(length)
771 };
772 index as usize
773}
774
775pub(crate) fn string_units(cx: &mut Cx<'_>, units: &[u16]) -> Result<Value, Throw> {
778 if units.len() > string::MAX_STRING {
779 return Err(vm_error::string_too_long(cx));
780 }
781 let result = if units.len() == 1 {
782 cx.heap.intern_units(units)
783 } else if units.is_empty() {
784 return Ok(Value::string(cx.realm.names.empty));
785 } else {
786 cx.heap.alloc_string_units(units)
787 };
788 result
789 .map(Value::string)
790 .map_err(|error| vm_error::heap_error(cx, error))
791}
792
793pub(crate) fn string_repr(cx: &mut Cx<'_>, repr: StringRepr) -> Result<Value, Throw> {
795 if repr.len() <= 1 {
796 let units: Vec<u16> = repr.units().collect();
797 return string_units(cx, &units);
798 }
799 cx.heap
800 .alloc_string_repr(repr)
801 .map(Value::string)
802 .map_err(|error| vm_error::heap_error(cx, error))
803}
804
805pub(crate) fn string_text(cx: &mut Cx<'_>, text: &str) -> Result<Value, Throw> {
807 if text.is_ascii() {
808 return string_repr(cx, StringRepr::OneByte(text.as_bytes().into()));
809 }
810 let units: Vec<u16> = text.encode_utf16().collect();
811 string_units(cx, &units)
812}
813
814pub(crate) fn to_string_id(cx: &mut Cx<'_>, value: Value) -> Result<StringId, Throw> {
817 if let Some(id) = value.as_string() {
818 return Ok(id);
819 }
820 let string = ops::to_string(cx, value)?;
821 cx.heap.roots().push(string);
822 Ok(string.as_string().expect("a string"))
823}
824
825pub(crate) fn this_string(cx: &mut Cx<'_>, site: &CallSite) -> Result<StringId, Throw> {
828 let this = site.this(cx);
829 if let Some(id) = this.as_string() {
830 return Ok(id);
831 }
832 if this.is_undefined() || this.is_null() {
833 return Err(vm_error::type_error(cx, "null or undefined are forbidden"));
834 }
835 to_string_id(cx, this)
836}
837
838pub(crate) fn this_object(cx: &mut Cx<'_>, site: &CallSite) -> Result<ObjectId, Throw> {
841 let this = site.this(cx);
842 if let Some(object) = this.as_object() {
843 return Ok(object);
844 }
845 let object = crate::vm::object::to_object(cx, this)?;
846 cx.heap.roots().push(Value::object(object));
847 Ok(object)
848}
849
850fn hidden() -> PropertyFlags {
853 PropertyFlags::data(true, false, true)
854}
855
856fn define(
858 cx: &mut Cx<'_>,
859 object: ObjectId,
860 name: &str,
861 value: Value,
862 flags: PropertyFlags,
863) -> Result<(), HeapError> {
864 let key = cx.heap.property_key(name)?;
865 define_key(cx, object, key, value, flags)
866}
867
868fn define_key(
869 cx: &mut Cx<'_>,
870 object: ObjectId,
871 key: crate::PropertyKey,
872 value: Value,
873 flags: PropertyFlags,
874) -> Result<(), HeapError> {
875 let mark = cx.heap.roots().mark();
876 cx.heap.roots().push(value);
877 let result = cx.heap.add_property(object, key, flags, value);
878 cx.heap.roots().truncate(mark);
879 result
880}
881
882pub(crate) fn define_name_length(
885 heap: &mut crate::Heap,
886 names: &Names,
887 function: ObjectId,
888 name: Value,
889 length: u32,
890) -> Result<(), HeapError> {
891 let flags = PropertyFlags::data(false, false, true);
892 let mark = heap.roots().mark();
893 heap.roots().push(name);
894 let result = heap
895 .add_property(
896 function,
897 Names::key(names.length),
898 flags,
899 Value::int32(length as i32),
900 )
901 .and_then(|()| heap.add_property(function, Names::key(names.name), flags, name));
902 heap.roots().truncate(mark);
903 result
904}
905
906fn native_named(
909 cx: &mut Cx<'_>,
910 native: Native,
911 name: &str,
912 data: Option<ObjectId>,
913) -> Result<ObjectId, HeapError> {
914 let prototype = cx.realm.intrinsic(Intrinsic::FunctionPrototype);
915 let function = cx
916 .heap
917 .alloc_native_closure(Some(prototype), native.index(), data)?;
918 cx.heap.roots().push(Value::object(function));
919 if native.is_constructor() {
920 cx.heap
921 .set_object_flag(function, crate::heap::object::flags::CONSTRUCTOR);
922 }
923 let name = if name.is_empty() {
924 cx.realm.names.empty
925 } else {
926 cx.heap.intern(name)?
927 };
928 let names = cx.realm.names;
929 define_name_length(
930 cx.heap,
931 &names,
932 function,
933 Value::string(name),
934 native.length(),
935 )?;
936 Ok(function)
937}
938
939fn native_function(cx: &mut Cx<'_>, native: Native) -> Result<ObjectId, HeapError> {
942 native_named(cx, native, native.js_name(), None)
943}
944
945pub(crate) fn native_closure(
949 cx: &mut Cx<'_>,
950 native: Native,
951 data: ObjectId,
952) -> Result<ObjectId, Throw> {
953 let mark = cx.heap.roots().mark();
954 cx.heap.roots().push(Value::object(data));
955 let result = native_named(cx, native, native.js_name(), Some(data));
956 cx.heap.roots().truncate(mark);
957 result.map_err(|error| vm_error::heap_error(cx, error))
958}
959
960pub(crate) fn native_data(cx: &mut Cx<'_>, slots: &[Value]) -> Result<ObjectId, Throw> {
962 cx.heap
963 .alloc_internal(
964 ObjectKind::Builtin,
965 crate::heap::object::InternalTag::NativeData,
966 None,
967 0,
968 slots,
969 Default::default(),
970 0,
971 )
972 .map_err(|error| vm_error::heap_error(cx, error))
973}
974
975fn methods(cx: &mut Cx<'_>, object: ObjectId, list: &[Native]) -> Result<(), HeapError> {
978 for &native in list {
979 let function = native_function(cx, native)?;
980 define(
981 cx,
982 object,
983 native.js_name(),
984 Value::object(function),
985 hidden(),
986 )?;
987 }
988 Ok(())
989}
990
991fn symbol_method(
994 cx: &mut Cx<'_>,
995 object: ObjectId,
996 symbol: crate::SymbolId,
997 native: Native,
998 flags: PropertyFlags,
999) -> Result<(), HeapError> {
1000 let function = native_function(cx, native)?;
1001 define_key(
1002 cx,
1003 object,
1004 crate::PropertyKey::symbol(symbol),
1005 Value::object(function),
1006 flags,
1007 )
1008}
1009
1010fn accessor(
1014 cx: &mut Cx<'_>,
1015 object: ObjectId,
1016 key: crate::PropertyKey,
1017 name: &str,
1018 getter: Option<Native>,
1019 setter: Option<Native>,
1020) -> Result<(), HeapError> {
1021 let get = match getter {
1022 Some(native) => Value::object(native_named(cx, native, &format!("get {name}"), None)?),
1023 None => Value::UNDEFINED,
1024 };
1025 let set = match setter {
1026 Some(native) => Value::object(native_named(cx, native, &format!("set {name}"), None)?),
1027 None => Value::UNDEFINED,
1028 };
1029 cx.heap
1030 .add_accessor(object, key, PropertyFlags::accessor(false, true), get, set)
1031}
1032
1033fn getter(cx: &mut Cx<'_>, object: ObjectId, name: &str, native: Native) -> Result<(), HeapError> {
1035 let key = cx.heap.property_key(name)?;
1036 accessor(cx, object, key, name, Some(native), None)
1037}
1038
1039fn install_constructor(cx: &mut Cx<'_>, native: Native) -> Result<ObjectId, HeapError> {
1044 let function = native_function(cx, native)?;
1045 let global = cx.realm.global();
1046 define(
1047 cx,
1048 global,
1049 native.js_name(),
1050 Value::object(function),
1051 hidden(),
1052 )?;
1053 Ok(function)
1054}
1055
1056fn link_constructor(
1060 cx: &mut Cx<'_>,
1061 function: ObjectId,
1062 prototype: ObjectId,
1063) -> Result<(), HeapError> {
1064 let names = cx.realm.names;
1065 cx.heap.add_property(
1066 function,
1067 Names::key(names.prototype),
1068 PropertyFlags::data(false, false, false),
1069 Value::object(prototype),
1070 )?;
1071 cx.heap.add_property(
1072 prototype,
1073 Names::key(names.constructor),
1074 hidden(),
1075 Value::object(function),
1076 )
1077}
1078
1079fn plain_object(
1081 cx: &mut Cx<'_>,
1082 prototype: Option<ObjectId>,
1083 slots: u32,
1084) -> Result<ObjectId, HeapError> {
1085 let object = cx
1086 .heap
1087 .alloc_object(ObjectKind::Ordinary, prototype, slots)?;
1088 cx.heap.roots().push(Value::object(object));
1089 Ok(object)
1090}
1091
1092fn to_string_tag(cx: &mut Cx<'_>, object: ObjectId, tag: &str) -> Result<(), HeapError> {
1095 let tag = cx.heap.intern(tag)?;
1096 let key = crate::PropertyKey::symbol(cx.realm.symbols.to_string_tag);
1097 cx.heap.add_property(
1098 object,
1099 key,
1100 PropertyFlags::data(false, false, true),
1101 Value::string(tag),
1102 )
1103}
1104
1105pub(crate) fn install(cx: &mut Cx<'_>) -> Result<ObjectId, HeapError> {
1108 let mark = cx.heap.roots().mark();
1109 let result = install_rooted(cx);
1110 cx.heap.roots().truncate(mark);
1111 result
1112}
1113
1114fn install_rooted(cx: &mut Cx<'_>) -> Result<ObjectId, HeapError> {
1115 let global = cx.realm.global();
1116 let constant = PropertyFlags::data(false, false, false);
1117 define(cx, global, "globalThis", Value::object(global), hidden())?;
1118 define(cx, global, "undefined", Value::UNDEFINED, constant)?;
1119 define(cx, global, "NaN", Value::number(f64::NAN), constant)?;
1120 define(
1121 cx,
1122 global,
1123 "Infinity",
1124 Value::number(f64::INFINITY),
1125 constant,
1126 )?;
1127 methods(
1128 cx,
1129 global,
1130 &[
1131 Native::ParseInt,
1132 Native::ParseFloat,
1133 Native::IsNaN,
1134 Native::IsFinite,
1135 ],
1136 )?;
1137 let eval = native_function(cx, Native::Eval)?;
1138 cx.set_intrinsic(Intrinsic::Eval, eval);
1139 define(cx, global, "eval", Value::object(eval), hidden())?;
1140 function::install(cx)?;
1141 object::install(cx)?;
1142 symbol::install(cx)?;
1143 reflect::install(cx)?;
1144 proxy::install(cx)?;
1145 array::install(cx)?;
1146 string::install(cx)?;
1147 iterator::install(cx)?;
1148 iterator_helpers::install(cx)?;
1149 generator::install(cx)?;
1150 generator::install_async_from_sync(cx)?;
1151 promise::install(cx)?;
1152 number::install(cx)?;
1153 boolean::install(cx)?;
1154 math::install(cx)?;
1155 bigint::install(cx)?;
1156 uri::install(cx)?;
1157 regexp::install(cx)?;
1158 date::install(cx)?;
1159 json::install(cx)?;
1160 collection::install(cx)?;
1161 buffer::install(cx)?;
1162 typed_array::install(cx)?;
1163 atomics::install(cx)?;
1164 error::install(cx)?;
1165 regexp::record_flag_cache(cx)?;
1166 to_string_tag(cx, global, "global")?;
1167 order_globals(cx, global)?;
1168 let message = cx.heap.intern("out of memory")?;
1169 let error = vm_error::new_error(cx, ErrorKind::Internal, Value::string(message))?;
1170 Ok(error.as_object().unwrap())
1171}
1172
1173const GLOBAL_ORDER: &[&str] = &[
1178 "Error",
1179 "EvalError",
1180 "RangeError",
1181 "ReferenceError",
1182 "SyntaxError",
1183 "TypeError",
1184 "URIError",
1185 "InternalError",
1186 "AggregateError",
1187 "Array",
1188 "Object",
1189 "Function",
1190 "Iterator",
1191 "parseInt",
1192 "parseFloat",
1193 "isNaN",
1194 "isFinite",
1195 "decodeURI",
1196 "decodeURIComponent",
1197 "encodeURI",
1198 "encodeURIComponent",
1199 "escape",
1200 "unescape",
1201 "Infinity",
1202 "NaN",
1203 "undefined",
1204 "eval",
1205 "Number",
1206 "Boolean",
1207 "String",
1208 "Math",
1209 "Reflect",
1210 "Symbol",
1211 "globalThis",
1212 "BigInt",
1213 "Date",
1214 "RegExp",
1215 "JSON",
1216 "Proxy",
1217 "Map",
1218 "Set",
1219 "WeakMap",
1220 "WeakSet",
1221 "ArrayBuffer",
1222 "SharedArrayBuffer",
1223 "Uint8ClampedArray",
1224 "Int8Array",
1225 "Uint8Array",
1226 "Int16Array",
1227 "Uint16Array",
1228 "Int32Array",
1229 "Uint32Array",
1230 "BigInt64Array",
1231 "BigUint64Array",
1232 "Float16Array",
1233 "Float32Array",
1234 "Float64Array",
1235 "DataView",
1236 "Atomics",
1237 "Promise",
1238 "WeakRef",
1239 "FinalizationRegistry",
1240];
1241
1242fn order_globals(cx: &mut Cx<'_>, global: ObjectId) -> Result<(), HeapError> {
1244 let mut keys = Vec::with_capacity(GLOBAL_ORDER.len());
1245 for name in GLOBAL_ORDER {
1246 keys.push(cx.heap.property_key(name)?);
1247 }
1248 debug_assert!(
1249 keys.iter()
1250 .all(|&key| cx.heap.lookup_own(global, key).is_some()),
1251 "every global in GLOBAL_ORDER is installed"
1252 );
1253 cx.heap.reorder_dictionary(global, &keys);
1254 Ok(())
1255}
1256
1257pub(crate) fn install_print(cx: &mut Cx<'_>) -> Result<(), HeapError> {
1260 let mark = cx.heap.roots().mark();
1261 let result = (|| {
1262 let global = cx.realm.global();
1263 let print = native_function(cx, Native::Print)?;
1264 define(cx, global, "print", Value::object(print), hidden())?;
1265 let prototype = cx.realm.intrinsic(Intrinsic::ObjectPrototype);
1266 let console = plain_object(cx, Some(prototype), 1)?;
1267 let log = native_function(cx, Native::ConsoleLog)?;
1268 define(cx, console, "log", Value::object(log), hidden())?;
1269 define(cx, global, "console", Value::object(console), hidden())
1270 })();
1271 cx.heap.roots().truncate(mark);
1272 result
1273}
1274
1275pub(crate) fn install_std(cx: &mut Cx<'_>) -> Result<(), HeapError> {
1277 let mark = cx.heap.roots().mark();
1278 let result = (|| {
1279 let global = cx.realm.global();
1280 for native in [Native::Load, Native::Read] {
1281 let function = native_function(cx, native)?;
1282 define(
1283 cx,
1284 global,
1285 native.js_name(),
1286 Value::object(function),
1287 hidden(),
1288 )?;
1289 }
1290 Ok(())
1291 })();
1292 cx.heap.roots().truncate(mark);
1293 result
1294}
1295
1296pub(crate) fn install_script_args(cx: &mut Cx<'_>, args: &[String]) -> Result<(), HeapError> {
1298 let mark = cx.heap.roots().mark();
1299 let result = (|| {
1300 let array = script_args_array(cx, args)?;
1301 let global = cx.realm.global();
1302 define(cx, global, "scriptArgs", Value::object(array), hidden())
1303 })();
1304 cx.heap.roots().truncate(mark);
1305 result
1306}
1307
1308fn script_args_array(cx: &mut Cx<'_>, args: &[String]) -> Result<ObjectId, HeapError> {
1310 let prototype = cx.realm.intrinsic(Intrinsic::ArrayPrototype);
1311 let array = cx.heap.alloc_array(Some(prototype), args.len() as u32)?;
1312 cx.heap.roots().push(Value::object(array));
1313 for (index, arg) in args.iter().enumerate() {
1314 let text = cx.heap.alloc_string(arg)?;
1315 cx.heap
1316 .set_element(array, index as u32, Value::string(text))?;
1317 }
1318 Ok(array)
1319}
1320
1321pub(crate) fn install_qjs_helpers(
1326 cx: &mut Cx<'_>,
1327 script_args: Option<&[String]>,
1328) -> Result<(), HeapError> {
1329 let mark = cx.heap.roots().mark();
1330 let result = (|| {
1331 let global = cx.realm.global();
1332 let all = PropertyFlags::data(true, true, true);
1333 let prototype = cx.realm.intrinsic(Intrinsic::ObjectPrototype);
1334 let console = plain_object(cx, Some(prototype), 1)?;
1335 let log = native_function(cx, Native::ConsoleLog)?;
1336 define(cx, console, "log", Value::object(log), all)?;
1337 define(cx, global, "console", Value::object(console), all)?;
1338 let performance = plain_object(cx, Some(prototype), 1)?;
1339 let now = native_function(cx, Native::PerformanceNow)?;
1340 define(cx, performance, "now", Value::object(now), all)?;
1341 define(cx, global, "performance", Value::object(performance), all)?;
1342 if let Some(args) = script_args {
1343 let array = script_args_array(cx, args)?;
1344 define(cx, global, "scriptArgs", Value::object(array), all)?;
1345 }
1346 let print = native_function(cx, Native::Print)?;
1347 define(cx, global, "print", Value::object(print), all)?;
1348 let load_script = native_function(cx, Native::LoadScript)?;
1349 define(cx, global, "__loadScript", Value::object(load_script), all)
1350 })();
1351 cx.heap.roots().truncate(mark);
1352 result
1353}
1354
1355pub(crate) fn typed_array_length_or_throw(cx: &mut Cx<'_>, object: ObjectId) -> Result<u64, Throw> {
1357 match crate::vm::typed::length(cx.heap, object) {
1358 Some(length) => Ok(length as u64),
1359 None => Err(vm_error::type_error(
1360 cx,
1361 "ArrayBuffer is detached or resized",
1362 )),
1363 }
1364}
1365
1366pub(crate) fn detach_array_buffer(cx: &mut Cx<'_>, site: CallSite) -> Result<Value, Throw> {
1368 let buffer = site.arg(cx, 0);
1371 let is_array_buffer = buffer.as_object().is_some_and(|object| {
1372 cx.heap.internal_tag(object) == crate::heap::object::InternalTag::ArrayBuffer
1373 });
1374 if is_array_buffer {
1375 buffer::detach(cx, buffer)?;
1376 }
1377 Ok(Value::UNDEFINED)
1378}
1379
1380pub(crate) use bigint::to_bigint;
1381pub(crate) use buffer::detach as detach_buffer;
1382pub(crate) use buffer::new_array_buffer;
1383pub(crate) use date::iso_string as date_iso_string;
1384pub(crate) use generator::async_from_sync_iterator;
1385pub(crate) use json::json_module_text;
1386pub(crate) use regexp::RegExpFlagCache;
1387
1388pub(crate) fn new_plain(cx: &mut Cx<'_>, slots: u32) -> Result<ObjectId, Throw> {
1390 let prototype = cx.realm.intrinsic(Intrinsic::ObjectPrototype);
1391 cx.heap
1392 .alloc_object(ObjectKind::Ordinary, Some(prototype), slots)
1393 .map_err(|error| vm_error::heap_error(cx, error))
1394}