ref: 6c8400d872634c40ca072d94696eadf0d87c9393
parent: 26cde86041665b800d807fa30f64eb96dd54e71b
author: Tor Andersson <tor@ccxvii.net>
date: Mon Jan 20 18:14:48 EST 2014
Fix CFunction calling conventions. 'this' is always argument 0 (even for constructors, where it is null). argc is the number of real arguments (not counting the 'this' object). for (i = 1; i <= argc; ++i) js_toXXX(J, i);
--- a/jsbarray.c
+++ b/jsbarray.c
@@ -2,10 +2,10 @@
#include "jsvalue.h"
#include "jsbuiltin.h"
-static int jsB_Array(js_State *J, int n) { return 0; }
-static int jsB_new_Array(js_State *J, int n) { return 0; }
+static int jsB_Array(js_State *J, int argc) { return 0; }
+static int jsB_new_Array(js_State *J, int argc) { return 0; }
-static int A_isArray(js_State *J, int n)
+static int A_isArray(js_State *J, int argc)
{
if (js_isobject(J, 1)) {
js_Object *T = js_toobject(J, 1);
--- a/jsbboolean.c
+++ b/jsbboolean.c
@@ -2,19 +2,19 @@
#include "jsvalue.h"
#include "jsbuiltin.h"
-static int jsB_new_Boolean(js_State *J, int n)
+static int jsB_new_Boolean(js_State *J, int argc)
{
- js_newboolean(J, js_toboolean(J, 0));
+ js_newboolean(J, js_toboolean(J, 1));
return 1;
}
-static int jsB_Boolean(js_State *J, int n)
+static int jsB_Boolean(js_State *J, int argc)
{
js_pushboolean(J, js_toboolean(J, 1));
return 1;
}
-static int Bp_toString(js_State *J, int n)
+static int Bp_toString(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
if (self->type != JS_CBOOLEAN) js_typeerror(J, "not a boolean");
@@ -22,7 +22,7 @@
return 1;
}
-static int Bp_valueOf(js_State *J, int n)
+static int Bp_valueOf(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
if (self->type != JS_CBOOLEAN) js_typeerror(J, "not a boolean");
--- a/jsberror.c
+++ b/jsberror.c
@@ -5,7 +5,7 @@
#define QQ(X) #X
#define Q(X) QQ(X)
-static int Ep_toString(js_State *J, int n)
+static int Ep_toString(js_State *J, int argc)
{
js_getproperty(J, 0, "name");
js_pushliteral(J, ": ");
@@ -16,17 +16,9 @@
}
#define DECL(NAME) \
- static int jsB_new_##NAME(js_State *J, int n) { \
+ static int jsB_##NAME(js_State *J, int argc) { \
js_pushobject(J, jsV_newobject(J, JS_CERROR, J->NAME##_prototype)); \
- if (n > 0) { \
- js_pushstring(J, js_tostring(J, 0)); \
- js_setproperty(J, -2, "message"); \
- } \
- return 1; \
- } \
- static int jsB_##NAME(js_State *J, int n) { \
- js_pushobject(J, jsV_newobject(J, JS_CERROR, J->NAME##_prototype)); \
- if (n > 1) { \
+ if (argc > 0) { \
js_pushstring(J, js_tostring(J, 1)); \
js_setproperty(J, -2, "message"); \
} \
@@ -49,13 +41,13 @@
jsB_props(J, "message", "an error has occurred");
jsB_propf(J, "toString", Ep_toString, 0);
}
- js_newcconstructor(J, jsB_Error, jsB_new_Error);
+ js_newcconstructor(J, jsB_Error, jsB_Error);
js_setglobal(J, "Error");
#define INIT(NAME) \
js_pushobject(J, J->NAME##_prototype); \
jsB_props(J, "name", Q(NAME)); \
- js_newcconstructor(J, jsB_##NAME, jsB_new_##NAME); \
+ js_newcconstructor(J, jsB_##NAME, jsB_##NAME); \
js_setglobal(J, Q(NAME));
INIT(EvalError);
--- a/jsbfunction.c
+++ b/jsbfunction.c
@@ -3,16 +3,16 @@
#include "jsvalue.h"
#include "jsbuiltin.h"
-static int jsB_new_Function(js_State *J, int n) { return 0; }
-static int jsB_Function(js_State *J, int n) { return 0; }
+static int jsB_new_Function(js_State *J, int argc) { return 0; }
+static int jsB_Function(js_State *J, int argc) { return 0; }
-static int jsB_Function_prototype(js_State *J, int n)
+static int jsB_Function_prototype(js_State *J, int argc)
{
js_pushundefined(J);
return 1;
}
-static int Fp_toString(js_State *J, int nargs)
+static int Fp_toString(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
char *s;
@@ -45,9 +45,9 @@
return 1;
}
-static int Fp_apply(js_State *J, int n)
+static int Fp_apply(js_State *J, int argc)
{
- int i, argc;
+ int i, n;
char name[20];
if (!js_iscallable(J, 0))
@@ -57,19 +57,19 @@
js_copy(J, 1);
js_getproperty(J, 2, "length");
- argc = js_tonumber(J, -1);
+ n = js_tonumber(J, -1);
js_pop(J, 1);
- for (i = 0; i < argc; ++i) {
+ for (i = 0; i < n; ++i) {
sprintf(name, "%d", i);
js_getproperty(J, 2, name);
}
- js_call(J, argc);
+ js_call(J, n);
return 1;
}
-static int Fp_call(js_State *J, int n)
+static int Fp_call(js_State *J, int argc)
{
int i;
@@ -78,11 +78,10 @@
js_copy(J, 0);
js_copy(J, 1);
+ for (i = 2; i <= argc; ++i)
+ js_copy(J, i);
- for (i = 1; i < n; ++i)
- js_copy(J, i + 1);
-
- js_call(J, n - 1);
+ js_call(J, argc - 1);
return 1;
}
--- a/jsbmath.c
+++ b/jsbmath.c
@@ -2,60 +2,60 @@
#include "jsvalue.h"
#include "jsbuiltin.h"
-static int Math_abs(js_State *J, int nargs) {
+static int Math_abs(js_State *J, int argc) {
return js_pushnumber(J, abs(js_tonumber(J, 1))), 1;
}
-static int Math_acos(js_State *J, int nargs) {
+static int Math_acos(js_State *J, int argc) {
return js_pushnumber(J, acos(js_tonumber(J, 1))), 1;
}
-static int Math_asin(js_State *J, int nargs) {
+static int Math_asin(js_State *J, int argc) {
return js_pushnumber(J, asin(js_tonumber(J, 1))), 1;
}
-static int Math_atan(js_State *J, int nargs) {
+static int Math_atan(js_State *J, int argc) {
return js_pushnumber(J, atan(js_tonumber(J, 1))), 1;
}
-static int Math_atan2(js_State *J, int nargs) {
+static int Math_atan2(js_State *J, int argc) {
return js_pushnumber(J, atan2(js_tonumber(J, 1), js_tonumber(J, 2))), 1;
}
-static int Math_ceil(js_State *J, int nargs) {
+static int Math_ceil(js_State *J, int argc) {
return js_pushnumber(J, ceil(js_tonumber(J, 1))), 1;
}
-static int Math_cos(js_State *J, int nargs) {
+static int Math_cos(js_State *J, int argc) {
return js_pushnumber(J, cos(js_tonumber(J, 1))), 1;
}
-static int Math_exp(js_State *J, int nargs) {
+static int Math_exp(js_State *J, int argc) {
return js_pushnumber(J, exp(js_tonumber(J, 1))), 1;
}
-static int Math_floor(js_State *J, int nargs) {
+static int Math_floor(js_State *J, int argc) {
return js_pushnumber(J, floor(js_tonumber(J, 1))), 1;
}
-static int Math_log(js_State *J, int nargs) {
+static int Math_log(js_State *J, int argc) {
return js_pushnumber(J, log(js_tonumber(J, 1))), 1;
}
-static int Math_pow(js_State *J, int nargs) {
+static int Math_pow(js_State *J, int argc) {
return js_pushnumber(J, pow(js_tonumber(J, 1), js_tonumber(J, 2))), 1;
}
-static int Math_random(js_State *J, int nargs) {
+static int Math_random(js_State *J, int argc) {
return js_pushnumber(J, (double)rand() / (RAND_MAX - 1)), 1;
}
-static int Math_round(js_State *J, int nargs) {
+static int Math_round(js_State *J, int argc) {
return js_pushnumber(J, round(js_tonumber(J, 1))), 1;
}
-static int Math_sin(js_State *J, int nargs) {
+static int Math_sin(js_State *J, int argc) {
return js_pushnumber(J, sin(js_tonumber(J, 1))), 1;
}
-static int Math_sqrt(js_State *J, int nargs) {
+static int Math_sqrt(js_State *J, int argc) {
return js_pushnumber(J, sqrt(js_tonumber(J, 1))), 1;
}
-static int Math_tan(js_State *J, int nargs) {
+static int Math_tan(js_State *J, int argc) {
return js_pushnumber(J, tan(js_tonumber(J, 1))), 1;
}
-static int Math_max(js_State *J, int nargs)
+static int Math_max(js_State *J, int argc)
{
double n = js_tonumber(J, 1);
int i;
- for (i = 2; i < nargs; i++) {
+ for (i = 2; i <= argc; ++i) {
double m = js_tonumber(J, i);
n = n > m ? n : m;
}
@@ -63,11 +63,11 @@
return 1;
}
-static int Math_min(js_State *J, int nargs)
+static int Math_min(js_State *J, int argc)
{
double n = js_tonumber(J, 1);
int i;
- for (i = 2; i < nargs; i++) {
+ for (i = 2; i <= argc; ++i) {
double m = js_tonumber(J, i);
n = n < m ? n : m;
}
--- a/jsbnumber.c
+++ b/jsbnumber.c
@@ -2,19 +2,19 @@
#include "jsvalue.h"
#include "jsbuiltin.h"
-static int jsB_new_Number(js_State *J, int n)
+static int jsB_new_Number(js_State *J, int argc)
{
- js_newnumber(J, n > 0 ? js_tonumber(J, 0) : 0);
+ js_newnumber(J, argc > 0 ? js_tonumber(J, 1) : 0);
return 1;
}
-static int jsB_Number(js_State *J, int n)
+static int jsB_Number(js_State *J, int argc)
{
- js_pushnumber(J, n > 0 ? js_tonumber(J, 1) : 0);
+ js_pushnumber(J, argc > 0 ? js_tonumber(J, 1) : 0);
return 1;
}
-static int Np_valueOf(js_State *J, int n)
+static int Np_valueOf(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
@@ -22,7 +22,7 @@
return 1;
}
-static int Np_toString(js_State *J, int n)
+static int Np_toString(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
@@ -30,7 +30,7 @@
return 1;
}
-static int Np_toFixed(js_State *J, int n)
+static int Np_toFixed(js_State *J, int argc)
{
char buf[40];
js_Object *self = js_toobject(J, 0);
@@ -41,7 +41,7 @@
return 1;
}
-static int Np_toExponential(js_State *J, int n)
+static int Np_toExponential(js_State *J, int argc)
{
char buf[40];
js_Object *self = js_toobject(J, 0);
@@ -52,7 +52,7 @@
return 1;
}
-static int Np_toPrecision(js_State *J, int n)
+static int Np_toPrecision(js_State *J, int argc)
{
char buf[40];
js_Object *self = js_toobject(J, 0);
--- a/jsbobject.c
+++ b/jsbobject.c
@@ -2,18 +2,18 @@
#include "jsvalue.h"
#include "jsbuiltin.h"
-static int jsB_new_Object(js_State *J, int n)
+static int jsB_new_Object(js_State *J, int argc)
{
- if (n == 0 || js_isundefined(J, 0) || js_isnull(J, 0))
+ if (argc == 0 || js_isundefined(J, 1) || js_isnull(J, 1))
js_newobject(J);
else
- js_pushobject(J, js_toobject(J, 0));
+ js_pushobject(J, js_toobject(J, 1));
return 1;
}
-static int jsB_Object(js_State *J, int n)
+static int jsB_Object(js_State *J, int argc)
{
- if (n == 0 || js_isundefined(J, 1) || js_isnull(J, 1))
+ if (argc == 0 || js_isundefined(J, 1) || js_isnull(J, 1))
js_newobject(J);
else
js_pushobject(J, js_toobject(J, 1));
@@ -20,7 +20,7 @@
return 1;
}
-static int Op_toString(js_State *J, int n)
+static int Op_toString(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
switch (self->type) {
@@ -41,13 +41,13 @@
return 1;
}
-static int Op_valueOf(js_State *J, int n)
+static int Op_valueOf(js_State *J, int argc)
{
/* return the 'this' object */
return 1;
}
-static int Op_hasOwnProperty(js_State *J, int n)
+static int Op_hasOwnProperty(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
const char *name = js_tostring(J, 1);
@@ -56,7 +56,7 @@
return 1;
}
-static int Op_isPrototypeOf(js_State *J, int n)
+static int Op_isPrototypeOf(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
if (js_isobject(J, 1)) {
@@ -73,7 +73,7 @@
return 1;
}
-static int Op_propertyIsEnumerable(js_State *J, int n)
+static int Op_propertyIsEnumerable(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
const char *name = js_tostring(J, 1);
--- a/jsbstring.c
+++ b/jsbstring.c
@@ -3,19 +3,19 @@
#include "jsbuiltin.h"
#include "jsutf.h"
-static int jsB_new_String(js_State *J, int n)
+static int jsB_new_String(js_State *J, int argc)
{
- js_newstring(J, n > 0 ? js_tostring(J, 0) : "");
+ js_newstring(J, argc > 0 ? js_tostring(J, 1) : "");
return 1;
}
-static int jsB_String(js_State *J, int n)
+static int jsB_String(js_State *J, int argc)
{
- js_pushliteral(J, n > 0 ? js_tostring(J, 1) : "");
+ js_pushliteral(J, argc > 0 ? js_tostring(J, 1) : "");
return 1;
}
-static int Sp_toString(js_State *J, int n)
+static int Sp_toString(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
@@ -23,7 +23,7 @@
return 1;
}
-static int Sp_valueOf(js_State *J, int n)
+static int Sp_valueOf(js_State *J, int argc)
{
js_Object *self = js_toobject(J, 0);
if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
@@ -46,7 +46,7 @@
return rune;
}
-static int Sp_charAt(js_State *J, int n)
+static int Sp_charAt(js_State *J, int argc)
{
char buf[UTFmax + 1];
const char *s = js_tostring(J, 0);
@@ -61,7 +61,7 @@
return 1;
}
-static int Sp_charCodeAt(js_State *J, int n)
+static int Sp_charCodeAt(js_State *J, int argc)
{
const char *s = js_tostring(J, 0);
int pos = js_tointeger(J, 1);
@@ -73,13 +73,13 @@
return 1;
}
-static int S_fromCharCode(js_State *J, int n)
+static int S_fromCharCode(js_State *J, int argc)
{
int i;
Rune c;
- char *s = malloc(n * UTFmax + 1), *p = s;
+ char *s = malloc(argc * UTFmax + 1), *p = s;
// TODO: guard malloc with try/catch
- for (i = 0; i < n; i++) {
+ for (i = 0; i <= argc; ++i) {
c = js_tointeger(J, i + 1); // TODO: ToUInt16()
p += runetochar(p, &c);
}
@@ -99,6 +99,18 @@
jsB_propf(J, "valueOf", Sp_valueOf, 0);
jsB_propf(J, "charAt", Sp_charAt, 1);
jsB_propf(J, "charCodeAt", Sp_charCodeAt, 1);
+ //jsB_propf(J, "concat", Sp_concat, 1);
+ //jsB_propf(J, "indexOf", Sp_indexOf, 1);
+ //jsB_propf(J, "lastIndexOf", Sp_lastIndexOf, 1);
+ //jsB_propf(J, "localeCompare", Sp_localeCompare, 1);
+ //jsB_propf(J, "slice", Sp_slice, 2);
+ // match (uses regexp)
+ // replace (uses regexp)
+ // search (uses regexp)
+ // split (uses regexp)
+ //jsB_propf(J, "substring", Sp_substring, 2);
+ //jsB_propf(J, "toLowerCase", Sp_toLowerCase, 0);
+ //jsB_propf(J, "toUpperCase", Sp_toUpperCase, 0);
}
js_newcconstructor(J, jsB_String, jsB_new_String);
{
--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -5,7 +5,7 @@
static int jsB_print(js_State *J, int argc)
{
int i;
- for (i = 1; i < argc; ++i) {
+ for (i = 1; i <= argc; ++i) {
const char *s = js_tostring(J, i);
if (i > 1) putchar(' ');
fputs(s, stdout);
--- a/jsrun.c
+++ b/jsrun.c
@@ -188,6 +188,10 @@
void js_pop(js_State *J, int n)
{
TOP -= n;
+ if (TOP < BOT) {
+ TOP = BOT;
+ js_error(J, "stack underflow!");
+ }
}
void js_copy(js_State *J, int idx)
@@ -389,7 +393,7 @@
static void jsR_callcfunction(js_State *J, int n, js_CFunction F)
{
- int rv = F(J, n + 1);
+ int rv = F(J, n);
if (rv) {
js_Value v = js_tovalue(J, -1);
TOP = --BOT; /* pop down to below function */
@@ -422,10 +426,13 @@
js_Object *prototype;
js_Object *newobj;
- /* built-in constructors create their own objects */
+ /* built-in constructors create their own objects, give them a 'null' this */
if (obj->type == JS_CCFUNCTION && obj->u.c.constructor) {
int savebot = BOT;
- BOT = TOP - n;
+ js_pushnull(J);
+ if (n > 0)
+ js_rot(J, n + 1);
+ BOT = TOP - n - 1;
jsR_callcfunction(J, n, obj->u.c.constructor);
BOT = savebot;
return;