}
+static njs_int_t
+njs_array_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t unused, njs_value_t *retval)
+{
+ int64_t length, i;
+ njs_int_t ret;
+ njs_array_t *array;
+ njs_value_t *this, *items, *mapfn;
+ njs_value_t arguments[3], value, result;
+ njs_function_t *function;
+
+ mapfn = njs_arg(args, nargs, 2);
+
+ if (njs_slow_path(!njs_is_function_or_undefined(mapfn))) {
+ njs_type_error(vm, "\"mapfn\" argument is not callable");
+ return NJS_ERROR;
+ }
+
+ function = NULL;
+ if (njs_is_function(mapfn)) {
+ function = njs_function(mapfn);
+ }
+
+ items = njs_arg(args, nargs, 1);
+
+ ret = njs_value_to_object(vm, items);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ ret = njs_object_length(vm, items, &length);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ this = njs_argument(args, 0);
+
+ if (njs_is_constructor(this)) {
+ njs_set_number(&arguments[0], length);
+
+ ret = njs_value_construct(vm, this, arguments, 1, &value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ } else {
+ array = njs_array_alloc(vm, 1, length, 0);
+ if (njs_slow_path(array == NULL)) {
+ return NJS_ERROR;
+ }
+
+ njs_set_array(&value, array);
+ }
+
+ arguments[0] = *njs_arg(args, nargs, 3);
+
+ for (i = 0; i < length; i++) {
+ ret = njs_value_property_i64(vm, items, i, &result);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ if (function != NULL) {
+ njs_value_assign(&arguments[1], &result);
+ njs_set_number(&arguments[2], i);
+
+ ret = njs_function_apply(vm, function, arguments, 3, &result);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+ }
+
+ ret = njs_value_create_data_prop_i64(vm, &value, i, &result, 0);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+ }
+
+ ret = njs_object_length_set(vm, &value, length);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ njs_value_assign(retval, &value);
+
+ return NJS_OK;
+}
+
+
static njs_int_t
njs_array_is_array(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval)
NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0),
+ NJS_DECLARE_PROP_NATIVE("from", njs_array_from, 1, 0),
+
NJS_DECLARE_PROP_NATIVE("isArray", njs_array_is_array, 1, 0),
NJS_DECLARE_PROP_NATIVE("of", njs_array_of, 0, 0),
njs_value_t *args, njs_uint_t nargs, njs_value_t *retval)
{
njs_int_t ret;
- njs_value_t this;
- njs_object_t *object;
njs_typed_array_t *array;
- object = njs_function_new_object(vm, constructor);
- if (njs_slow_path(object == NULL)) {
- return NJS_ERROR;
- }
-
- njs_set_object(&this, object);
-
- ret = njs_function_call2(vm, njs_function(constructor), &this, args,
- nargs, retval, 1);
+ ret = njs_value_construct(vm, constructor, args, nargs, retval);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
}
+njs_int_t
+njs_value_construct(njs_vm_t *vm, njs_value_t *constructor, njs_value_t *args,
+ njs_uint_t nargs, njs_value_t *retval)
+{
+ njs_value_t this;
+ njs_object_t *object;
+
+ object = njs_function_new_object(vm, constructor);
+ if (njs_slow_path(object == NULL)) {
+ return NJS_ERROR;
+ }
+
+ njs_set_object(&this, object);
+
+ return njs_function_call2(vm, njs_function(constructor), &this, args,
+ nargs, retval, 1);
+}
+
+
njs_int_t
njs_value_species_constructor(njs_vm_t *vm, njs_value_t *object,
njs_value_t *default_constructor, njs_value_t *dst)
void njs_symbol_conversion_failed(njs_vm_t *vm, njs_bool_t to_string);
+njs_int_t njs_value_construct(njs_vm_t *vm, njs_value_t *constructor,
+ njs_value_t *args, njs_uint_t nargs, njs_value_t *retval);
njs_int_t njs_value_species_constructor(njs_vm_t *vm, njs_value_t *object,
njs_value_t *default_constructor, njs_value_t *dst);
return NULL;
}
+ njs_assert(njs_is_function(constructor));
+
function = njs_function(constructor);
if (function->bound != NULL) {
{ njs_str("Array.isArray([]) ? 'true' : 'false'"),
njs_str("true") },
+ { njs_str("["
+ " [undefined],"
+ " [null],"
+ " ['foo'],"
+ " ['foo', c => c.toUpperCase()],"
+ " [{length: 3, 1:'a', 2:'b'}],"
+ " [[7,,9], v => v*2],"
+ "].map(args => { try { return Array.from.apply(Array,args) }"
+ " catch (e) {return e.toString()}})"),
+ njs_str("TypeError: cannot convert null or undefined to object,"
+ "TypeError: cannot convert null or undefined to object,"
+ "f,o,o,"
+ "F,O,O,"
+ ",a,b,"
+ "14,NaN,18"
+ ) },
+
+ { njs_str("function f() {return Array.from(arguments);}; f(1,2,3)"),
+ njs_str("1,2,3") },
+
+ { njs_str("Array.from({ length: 5 }, (v, i) => i)"),
+ njs_str("0,1,2,3,4") },
+
+ { njs_str("const range = (start, stop, step) =>"
+ "Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + i * step);"
+ "range(1, 10, 2)"),
+ njs_str("1,3,5,7,9") },
+
+ { njs_str("var a = Array.from.call(Object, { length: 2, 0:7, 1:9 });"
+ "[a[0], a[1], Array.isArray(a)]"),
+ njs_str("7,9,false") },
+
{ njs_str("Array.of()"),
njs_str("") },
njs_str("length,name,prototype") },
{ njs_str("Object.getOwnPropertyNames(Array)"),
- njs_str("name,length,prototype,isArray,of") },
+ njs_str("name,length,prototype,from,isArray,of") },
{ njs_str("Object.getOwnPropertyNames(Array.isArray)"),
njs_str("name,length") },