> eval.call.call(function(){return String})
Segmentation fault
> URIError.apply.apply(RegExp)
Segmentation fault
> isNaN.apply.call(isNaN)
Segmentation fault
@drsm
See the below code.
function.apply(thisArg, [argsArray])
var a = {};
a.foo = function() {
console.log(this === a); // true
}
a.foo();
URIError.apply.apply(undefined)
I tried in nodejs. It throws TypeError: URIError.apply.apply is not a function. Why?
URIError.apply.apply the same as URIError.apply is?console.log(URIError.apply.apply === URIError.apply); // In nodejs, true
this?URIError.apply.apply(undefined);
Is URIError.apply or undefined?
deleted.
@hongzhidao
Is URIError.apply.apply the same as URIError.apply is?
Yes, they are both equal to Function.prototype.apply.
With apply function. What is the value of
this?URIError.apply.apply(undefined);
this = URIError.apply thisArg = undefined
see apply
@hongzhidao
I tried in nodejs. It throws
TypeError: URIError.apply.apply is not a function. Why?
Yes, error message is confusing there:
> var fn = Function.prototype.apply;
undefined
> fn()
Thrown:
TypeError: fn is not a function
> var o = { f: fn }
undefined
> o.f()
Thrown:
TypeError: o.f is not a function
> var f = function() { console.log('f'); }
undefined
> f.x = fn
[Function: apply]
> f.x()
f
undefined
@drsm
Two questions.
1.
console.log(typeof(eval.call)); // function
eval.call.call(1);
^
TypeError: eval.call is not a function
As eval.call is a function, why can't we use eval.call.call(1)?
eval.call(Number) and eval.call.call(Number)?@xeioex did you find these recent issues by test262?
@hongzhidao
there is a bad confusing error message in nodejs:
root@node:~# eshost -x 'eval.call.call(1)'
#### ch
TypeError: Function.prototype.call: 'this' is not a Function object
#### jsc
TypeError: 1 is not a function
#### sm
TypeError: Function.prototype.call called on incompatible number
#### v8
TypeError: eval.call.call is not a function
#### xs
TypeError: ?.call: this is no Function instance
eval.call.call(1);
The function object eval.call === Function.prototype.call is called on the primitive value 1
the same:
> var x = Function.prototype.call.bind(1);
undefined
> x()
Thrown:
TypeError: x is not a function
> typeof x
'function'
Is there any difference between
eval.call(Number)andeval.call.call(Number)?
evalis called onNumber
> Number.eval = eval
[Function: eval]
> Number.eval()
undefined
> eval.bind(Number)()
undefined
eval.call === Function.prototype.call is called on Number> Function.prototype.call.bind(Number)()
0
> eval.call.call.call(Number)
0
> eval.call.call.call.call(Number)
0
> eval.call === eval.call.call.call
true
the_object.the_function(arguments)
the_function.call(the_object, arguments)
the_function.apply(the_object, [arguments])
@xeioex
deleted.
Help test and add unit tests, please. @drsm @xeioex
(I'm not familiar with call/apply)
What's the actual return value of xxx.call(...)? For example.
eval.call.call(function() { return 1 });
BTW, according to my understanding.
Function.prototype.call always call this as a function.
So, eval.call(...) will call the eval function since this is object eval with property call.
eval.call.call(foo) will call foo since this is bound to foo.
Right?
@hongzhidao
Function.prototype.callalways callthisas a function.
So,eval.call(...)will call theevalfunction sincethisis objectevalwith propertycall.
eval.call.call(foo)will callfoosincethisis bound tofoo.
Right?
Yes.
@hongzhidao
>> var x = function() { console.log('x'); }
undefined
>> eval.call(x)
InternalError: Not implemented
at eval (native)
at Function.prototype.call (native)
at main (native)
>> eval.call.call(x) // should call x there
[Function]
>> x.call()
x
undefined
>> x()
x
undefined
here is the test:
> var fn = Function.prototype.call;
undefined
> fn.call(() => 1)
1
> fn.call(fn, () => 1)
1
> fn.call(fn, fn, () => 1)
1
deleted.
@xeioex @drsm
Here are two patches. (done)
# HG changeset patch
# User hongzhidao <[email protected]>
# Date 1556279874 -28800
# Node ID 73effc1318a90da6cf8fa0204c2318e0733d2bff
# Parent 43dc900bc914b1d8d2eaf36008f8690d21c54447
Improved njs_function_native_call().
diff -r 43dc900bc914 -r 73effc1318a9 njs/njs_function.c
--- a/njs/njs_function.c Thu Apr 25 19:50:20 2019 +0300
+++ b/njs/njs_function.c Fri Apr 26 19:57:54 2019 +0800
@@ -566,7 +566,7 @@ njs_function_lambda_call(njs_vm_t *vm, n
njs_ret_t
njs_function_native_call(njs_vm_t *vm, njs_function_native_t native,
njs_value_t *args, uint8_t *args_types, nxt_uint_t nargs,
- njs_index_t retval)
+ njs_index_t retval, u_char *return_address)
{
njs_ret_t ret;
njs_value_t *value;
@@ -617,6 +617,8 @@ njs_function_native_call(njs_vm_t *vm, n
*value = vm->retval;
}
+ vm->current = return_address;
+
njs_function_frame_free(vm, frame);
return NXT_OK;
diff -r 43dc900bc914 -r 73effc1318a9 njs/njs_function.h
--- a/njs/njs_function.h Thu Apr 25 19:50:20 2019 +0300
+++ b/njs/njs_function.h Fri Apr 26 19:57:54 2019 +0800
@@ -173,7 +173,7 @@ njs_ret_t njs_function_lambda_call(njs_v
u_char *return_address);
njs_ret_t njs_function_native_call(njs_vm_t *vm, njs_function_native_t native,
njs_value_t *args, uint8_t *args_types, nxt_uint_t nargs,
- njs_index_t retval);
+ njs_index_t retval, u_char *return_address);
void njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *frame);
diff -r 43dc900bc914 -r 73effc1318a9 njs/njs_vm.c
--- a/njs/njs_vm.c Thu Apr 25 19:50:20 2019 +0300
+++ b/njs/njs_vm.c Fri Apr 26 19:57:54 2019 +0800
@@ -2047,7 +2047,8 @@ njs_vmcode_function_call(njs_vm_t *vm, n
ret = njs_function_native_call(vm, function->u.native,
frame->arguments,
function->args_types, frame->nargs,
- (njs_index_t) retval);
+ (njs_index_t) retval,
+ return_address);
}
} else {
@@ -2055,16 +2056,7 @@ njs_vmcode_function_call(njs_vm_t *vm, n
return_address);
}
- switch (ret) {
- case NXT_OK:
- return sizeof(njs_vmcode_function_call_t);
-
- case NJS_APPLIED:
- return 0;
-
- default:
- return ret;
- }
+ return (ret == NJS_APPLIED) ? 0 : ret;
}
@@ -2304,19 +2296,9 @@ njs_vmcode_continuation(njs_vm_t *vm, nj
ret = njs_function_native_call(vm, cont->function, frame->arguments,
cont->args_types, frame->nargs,
- cont->retval);
-
- switch (ret) {
- case NXT_OK:
- vm->current = return_address;
- /* Fall through. */
-
- case NJS_APPLIED:
- return 0;
-
- default:
- return ret;
- }
+ cont->retval, return_address);
+
+ return (ret == NJS_APPLIED) ? 0 : ret;
}
# HG changeset patch
# User hongzhidao <[email protected]>
# Date 1556281097 -28800
# Node ID 893b82c75279cd114b45093b81f20889c691162f
# Parent 73effc1318a90da6cf8fa0204c2318e0733d2bff
Fixed function prototype call and apply.
diff -r 73effc1318a9 -r 893b82c75279 njs/njs_function.c
--- a/njs/njs_function.c Fri Apr 26 19:57:54 2019 +0800
+++ b/njs/njs_function.c Fri Apr 26 20:18:17 2019 +0800
@@ -31,7 +31,6 @@ njs_function_alloc(njs_vm_t *vm, njs_fun
goto fail;
}
-
/*
* nxt_mp_zalloc() does also:
* nxt_lvlhsh_init(&function->object.hash);
@@ -312,6 +311,10 @@ njs_function_native_frame(njs_vm_t *vm,
frame->nargs = function->args_offset + nargs;
frame->ctor = ctor;
+ if (continuation_size > 0) {
+ frame->continuation = njs_vm_continuation(vm);
+ }
+
value = (njs_value_t *) (njs_continuation(frame) + continuation_size);
frame->arguments = value;
@@ -770,6 +773,10 @@ njs_function_frame_free(njs_vm_t *vm, nj
do {
previous = frame->previous;
+ if (frame->continuation != NULL) {
+ vm->current = frame->continuation->return_address;
+ }
+
/* GC: free frame->local, etc. */
if (frame->size != 0) {
diff -r 73effc1318a9 -r 893b82c75279 njs/njs_function.h
--- a/njs/njs_function.h Fri Apr 26 19:57:54 2019 +0800
+++ b/njs/njs_function.h Fri Apr 26 20:18:17 2019 +0800
@@ -104,6 +104,8 @@ struct njs_native_frame_s {
njs_function_t *function;
njs_native_frame_t *previous;
+ njs_continuation_t *continuation;
+
njs_value_t *arguments;
njs_object_t *arguments_object;
diff -r 73effc1318a9 -r 893b82c75279 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Fri Apr 26 19:57:54 2019 +0800
+++ b/njs/test/njs_unit_test.c Fri Apr 26 20:18:17 2019 +0800
@@ -6039,6 +6039,21 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("function f (x){ return x**2}; f(2\n)"),
nxt_string("4") },
+ { nxt_string("var fn = Function.prototype.call; fn.call(() => 1)"),
+ nxt_string("1") },
+
+ { nxt_string("var fn = Function.prototype.call; fn.call(fn, () => 1)"),
+ nxt_string("1") },
+
+ { nxt_string("var fn = Function.prototype.call; fn.call(fn, fn, () => 1)"),
+ nxt_string("1") },
+
+ { nxt_string("eval.call.call(Number)"),
+ nxt_string("0") },
+
+ { nxt_string("URIError.apply.apply(RegExp)"),
+ nxt_string("/(?:)/") },
+
/* Recursive factorial. */
{ nxt_string("function f(a) {"
@hongzhidao
Works fine for me, thanks!
>> var fn = Function.prototype.apply, x = (...a) => [this === x, a.join()]; fn.call(x, x, [1,2,3])
[
false,
'1,2,3'
]
>> var fn = Function.prototype.apply, x = function(...a) { return [this === x, a.join()] }; fn.call(x, x, [1,2,3])
[
true,
'1,2,3'
]
@xeioex wait a moment.
For the second patch, I think it's still not ideal.
@xeioex
Here's the final version of this patch.
# HG changeset patch
# User hongzhidao <[email protected]>
# Date 1556279874 -28800
# Node ID 73effc1318a90da6cf8fa0204c2318e0733d2bff
# Parent 43dc900bc914b1d8d2eaf36008f8690d21c54447
Improved njs_function_native_call().
diff -r 43dc900bc914 -r 73effc1318a9 njs/njs_function.c
--- a/njs/njs_function.c Thu Apr 25 19:50:20 2019 +0300
+++ b/njs/njs_function.c Fri Apr 26 19:57:54 2019 +0800
@@ -566,7 +566,7 @@ njs_function_lambda_call(njs_vm_t *vm, n
njs_ret_t
njs_function_native_call(njs_vm_t *vm, njs_function_native_t native,
njs_value_t *args, uint8_t *args_types, nxt_uint_t nargs,
- njs_index_t retval)
+ njs_index_t retval, u_char *return_address)
{
njs_ret_t ret;
njs_value_t *value;
@@ -617,6 +617,8 @@ njs_function_native_call(njs_vm_t *vm, n
*value = vm->retval;
}
+ vm->current = return_address;
+
njs_function_frame_free(vm, frame);
return NXT_OK;
diff -r 43dc900bc914 -r 73effc1318a9 njs/njs_function.h
--- a/njs/njs_function.h Thu Apr 25 19:50:20 2019 +0300
+++ b/njs/njs_function.h Fri Apr 26 19:57:54 2019 +0800
@@ -173,7 +173,7 @@ njs_ret_t njs_function_lambda_call(njs_v
u_char *return_address);
njs_ret_t njs_function_native_call(njs_vm_t *vm, njs_function_native_t native,
njs_value_t *args, uint8_t *args_types, nxt_uint_t nargs,
- njs_index_t retval);
+ njs_index_t retval, u_char *return_address);
void njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *frame);
diff -r 43dc900bc914 -r 73effc1318a9 njs/njs_vm.c
--- a/njs/njs_vm.c Thu Apr 25 19:50:20 2019 +0300
+++ b/njs/njs_vm.c Fri Apr 26 19:57:54 2019 +0800
@@ -2047,7 +2047,8 @@ njs_vmcode_function_call(njs_vm_t *vm, n
ret = njs_function_native_call(vm, function->u.native,
frame->arguments,
function->args_types, frame->nargs,
- (njs_index_t) retval);
+ (njs_index_t) retval,
+ return_address);
}
} else {
@@ -2055,16 +2056,7 @@ njs_vmcode_function_call(njs_vm_t *vm, n
return_address);
}
- switch (ret) {
- case NXT_OK:
- return sizeof(njs_vmcode_function_call_t);
-
- case NJS_APPLIED:
- return 0;
-
- default:
- return ret;
- }
+ return (ret == NJS_APPLIED) ? 0 : ret;
}
@@ -2304,19 +2296,9 @@ njs_vmcode_continuation(njs_vm_t *vm, nj
ret = njs_function_native_call(vm, cont->function, frame->arguments,
cont->args_types, frame->nargs,
- cont->retval);
-
- switch (ret) {
- case NXT_OK:
- vm->current = return_address;
- /* Fall through. */
-
- case NJS_APPLIED:
- return 0;
-
- default:
- return ret;
- }
+ cont->retval, return_address);
+
+ return (ret == NJS_APPLIED) ? 0 : ret;
}
# HG changeset patch
# User hongzhidao <[email protected]>
# Date 1556285404 -28800
# Node ID f2e74147ee5474e10a16159c45a876c92a4775a0
# Parent 73effc1318a90da6cf8fa0204c2318e0733d2bff
Improved njs_vm_continuation().
diff -r 73effc1318a9 -r f2e74147ee54 njs/njs_function.c
--- a/njs/njs_function.c Fri Apr 26 19:57:54 2019 +0800
+++ b/njs/njs_function.c Fri Apr 26 21:30:04 2019 +0800
@@ -294,6 +294,7 @@ njs_function_native_frame(njs_vm_t *vm,
size_t continuation_size, nxt_bool_t ctor)
{
size_t size;
+ u_char *continuation;
nxt_uint_t n;
njs_value_t *value, *bound;
njs_native_frame_t *frame;
@@ -312,7 +313,13 @@ njs_function_native_frame(njs_vm_t *vm,
frame->nargs = function->args_offset + nargs;
frame->ctor = ctor;
- value = (njs_value_t *) (njs_continuation(frame) + continuation_size);
+ continuation = (u_char *) frame + NJS_NATIVE_FRAME_SIZE;
+
+ if (continuation_size > 0) {
+ frame->continuation = (njs_continuation_t *) continuation;
+ }
+
+ value = (njs_value_t *) (continuation + continuation_size);
frame->arguments = value;
bound = function->bound;
@@ -770,6 +777,10 @@ njs_function_frame_free(njs_vm_t *vm, nj
do {
previous = frame->previous;
+ if (frame->continuation != NULL) {
+ vm->current = frame->continuation->return_address;
+ }
+
/* GC: free frame->local, etc. */
if (frame->size != 0) {
diff -r 73effc1318a9 -r f2e74147ee54 njs/njs_function.h
--- a/njs/njs_function.h Fri Apr 26 19:57:54 2019 +0800
+++ b/njs/njs_function.h Fri Apr 26 21:30:04 2019 +0800
@@ -66,10 +66,7 @@ typedef struct {
#define njs_vm_continuation(vm) \
- (void *) njs_continuation((vm)->top_frame)
-
-#define njs_continuation(frame) \
- ((u_char *) frame + NJS_NATIVE_FRAME_SIZE)
+ (void *) ((vm)->top_frame->continuation)
#define njs_continuation_size(size) \
nxt_align_size(sizeof(size), sizeof(njs_value_t))
@@ -104,6 +101,8 @@ struct njs_native_frame_s {
njs_function_t *function;
njs_native_frame_t *previous;
+ njs_continuation_t *continuation;
+
njs_value_t *arguments;
njs_object_t *arguments_object;
diff -r 73effc1318a9 -r f2e74147ee54 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Fri Apr 26 19:57:54 2019 +0800
+++ b/njs/test/njs_unit_test.c Fri Apr 26 21:30:04 2019 +0800
@@ -6039,6 +6039,21 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("function f (x){ return x**2}; f(2\n)"),
nxt_string("4") },
+ { nxt_string("var fn = Function.prototype.call; fn.call(() => 1)"),
+ nxt_string("1") },
+
+ { nxt_string("var fn = Function.prototype.call; fn.call(fn, () => 1)"),
+ nxt_string("1") },
+
+ { nxt_string("var fn = Function.prototype.call; fn.call(fn, fn, () => 1)"),
+ nxt_string("1") },
+
+ { nxt_string("eval.call.call(Number)"),
+ nxt_string("0") },
+
+ { nxt_string("URIError.apply.apply(RegExp)"),
+ nxt_string("/(?:)/") },
+
/* Recursive factorial. */
{ nxt_string("function f(a) {"
@drsm thanks for your help :)