shithub: libmujs

Download patch

ref: 278590fcb46b63afcff326da4241786ab9559e86
parent: 71ffe074957b3bf4f12bf79ec9b16297a4557b66
author: Tor Andersson <tor.andersson@artifex.com>
date: Thu Dec 1 05:18:37 EST 2022

Merge the small private header files into jsi.h

--- a/jsarray.c
+++ b/jsarray.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 
 int js_getlength(js_State *J, int idx)
 {
--- a/jsboolean.c
+++ b/jsboolean.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 
 static void jsB_new_Boolean(js_State *J)
 {
--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -1,8 +1,4 @@
 #include "jsi.h"
-#include "jslex.h"
-#include "jscompile.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 #include "regexp.h"
 
 static void jsB_globalf(js_State *J, const char *name, js_CFunction cfun, int n)
--- a/jsbuiltin.h
+++ /dev/null
@@ -1,21 +1,0 @@
-#ifndef js_builtin_h
-#define js_builtin_h
-
-void jsB_init(js_State *J);
-void jsB_initobject(js_State *J);
-void jsB_initarray(js_State *J);
-void jsB_initfunction(js_State *J);
-void jsB_initboolean(js_State *J);
-void jsB_initnumber(js_State *J);
-void jsB_initstring(js_State *J);
-void jsB_initregexp(js_State *J);
-void jsB_initerror(js_State *J);
-void jsB_initmath(js_State *J);
-void jsB_initjson(js_State *J);
-void jsB_initdate(js_State *J);
-
-void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n);
-void jsB_propn(js_State *J, const char *name, double number);
-void jsB_props(js_State *J, const char *name, const char *string);
-
-#endif
--- a/jscompile.c
+++ b/jscompile.c
@@ -1,8 +1,4 @@
 #include "jsi.h"
-#include "jslex.h"
-#include "jsparse.h"
-#include "jscompile.h"
-#include "jsvalue.h" /* for jsV_numbertostring */
 
 #define cexp jsC_cexp /* collision with math.h */
 
--- a/jscompile.h
+++ /dev/null
@@ -1,141 +1,0 @@
-#ifndef js_compile_h
-#define js_compile_h
-
-enum js_OpCode
-{
-	OP_POP,		/* A -- */
-	OP_DUP,		/* A -- A A */
-	OP_DUP2,	/* A B -- A B A B */
-	OP_ROT2,	/* A B -- B A */
-	OP_ROT3,	/* A B C -- C A B */
-	OP_ROT4,	/* A B C D -- D A B C */
-
-	OP_INTEGER,	/* -K- (number-32768) */
-	OP_NUMBER,	/* -N- <number> */
-	OP_STRING,	/* -S- <string> */
-	OP_CLOSURE,	/* -F- <closure> */
-
-	OP_NEWARRAY,
-	OP_NEWOBJECT,
-	OP_NEWREGEXP,	/* -S,opts- <regexp> */
-
-	OP_UNDEF,
-	OP_NULL,
-	OP_TRUE,
-	OP_FALSE,
-
-	OP_THIS,
-	OP_CURRENT,	/* currently executing function object */
-
-	OP_GETLOCAL,	/* -K- <value> */
-	OP_SETLOCAL,	/* <value> -K- <value> */
-	OP_DELLOCAL,	/* -K- false */
-
-	OP_HASVAR,	/* -S- ( <value> | undefined ) */
-	OP_GETVAR,	/* -S- <value> */
-	OP_SETVAR,	/* <value> -S- <value> */
-	OP_DELVAR,	/* -S- <success> */
-
-	OP_IN,		/* <name> <obj> -- <exists?> */
-
-	OP_INITARRAY,	/* <obj> <val> -- <obj> */
-	OP_INITPROP,	/* <obj> <key> <val> -- <obj> */
-	OP_INITGETTER,	/* <obj> <key> <closure> -- <obj> */
-	OP_INITSETTER,	/* <obj> <key> <closure> -- <obj> */
-
-	OP_GETPROP,	/* <obj> <name> -- <value> */
-	OP_GETPROP_S,	/* <obj> -S- <value> */
-	OP_SETPROP,	/* <obj> <name> <value> -- <value> */
-	OP_SETPROP_S,	/* <obj> <value> -S- <value> */
-	OP_DELPROP,	/* <obj> <name> -- <success> */
-	OP_DELPROP_S,	/* <obj> -S- <success> */
-
-	OP_ITERATOR,	/* <obj> -- <iobj> */
-	OP_NEXTITER,	/* <iobj> -- ( <iobj> <name> true | false ) */
-
-	OP_EVAL,	/* <args...> -(numargs)- <returnvalue> */
-	OP_CALL,	/* <closure> <this> <args...> -(numargs)- <returnvalue> */
-	OP_NEW,		/* <closure> <args...> -(numargs)- <returnvalue> */
-
-	OP_TYPEOF,
-	OP_POS,
-	OP_NEG,
-	OP_BITNOT,
-	OP_LOGNOT,
-	OP_INC,		/* <x> -- ToNumber(x)+1 */
-	OP_DEC,		/* <x> -- ToNumber(x)-1 */
-	OP_POSTINC,	/* <x> -- ToNumber(x)+1 ToNumber(x) */
-	OP_POSTDEC,	/* <x> -- ToNumber(x)-1 ToNumber(x) */
-
-	OP_MUL,
-	OP_DIV,
-	OP_MOD,
-	OP_ADD,
-	OP_SUB,
-	OP_SHL,
-	OP_SHR,
-	OP_USHR,
-	OP_LT,
-	OP_GT,
-	OP_LE,
-	OP_GE,
-	OP_EQ,
-	OP_NE,
-	OP_STRICTEQ,
-	OP_STRICTNE,
-	OP_JCASE,
-	OP_BITAND,
-	OP_BITXOR,
-	OP_BITOR,
-
-	OP_INSTANCEOF,
-
-	OP_THROW,
-
-	OP_TRY,		/* -ADDR- /jump/ or -ADDR- <exception> */
-	OP_ENDTRY,
-
-	OP_CATCH,	/* push scope chain with exception variable */
-	OP_ENDCATCH,
-
-	OP_WITH,
-	OP_ENDWITH,
-
-	OP_DEBUGGER,
-	OP_JUMP,
-	OP_JTRUE,
-	OP_JFALSE,
-	OP_RETURN,
-};
-
-struct js_Function
-{
-	const char *name;
-	int script;
-	int lightweight;
-	int strict;
-	int arguments;
-	int numparams;
-
-	js_Instruction *code;
-	int codecap, codelen;
-
-	js_Function **funtab;
-	int funcap, funlen;
-
-	const char **vartab;
-	int varcap, varlen;
-
-	const char *filename;
-	int line, lastline;
-
-	js_Function *gcnext;
-	int gcmark;
-};
-
-js_Function *jsC_compilefunction(js_State *J, js_Ast *prog);
-js_Function *jsC_compilescript(js_State *J, js_Ast *prog, int default_strict);
-const char *jsC_opcodestring(enum js_OpCode opcode);
-void jsC_dumpfunction(js_State *J, js_Function *fun);
-
-#endif
--- a/jsdate.c
+++ b/jsdate.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 
 #include <time.h>
 
--- a/jsdump.c
+++ b/jsdump.c
@@ -1,7 +1,4 @@
 #include "jsi.h"
-#include "jsparse.h"
-#include "jscompile.h"
-#include "jsvalue.h"
 
 #include "utf.h"
 
--- a/jserror.c
+++ b/jserror.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 
 #define QQ(X) #X
 #define Q(X) QQ(X)
--- a/jsfunction.c
+++ b/jsfunction.c
@@ -1,8 +1,4 @@
 #include "jsi.h"
-#include "jsparse.h"
-#include "jscompile.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 
 static void jsB_Function(js_State *J)
 {
--- a/jsgc.c
+++ b/jsgc.c
@@ -1,8 +1,4 @@
 #include "jsi.h"
-#include "jscompile.h"
-#include "jsvalue.h"
-#include "jsrun.h"
-
 #include "regexp.h"
 
 static void jsG_freeenvironment(js_State *J, js_Environment *env)
--- a/jsi.h
+++ b/jsi.h
@@ -280,4 +280,592 @@
 	js_Jumpbuf trybuf[JS_TRYLIMIT];
 };
 
+/* Values */
+
+typedef struct js_Property js_Property;
+typedef struct js_Iterator js_Iterator;
+
+/* Hint to ToPrimitive() */
+enum {
+	JS_HNONE,
+	JS_HNUMBER,
+	JS_HSTRING
+};
+
+enum js_Type {
+	JS_TSHRSTR, /* type tag doubles as string zero-terminator */
+	JS_TUNDEFINED,
+	JS_TNULL,
+	JS_TBOOLEAN,
+	JS_TNUMBER,
+	JS_TLITSTR,
+	JS_TMEMSTR,
+	JS_TOBJECT,
+};
+
+enum js_Class {
+	JS_COBJECT,
+	JS_CARRAY,
+	JS_CFUNCTION,
+	JS_CSCRIPT, /* function created from global/eval code */
+	JS_CCFUNCTION, /* built-in function */
+	JS_CERROR,
+	JS_CBOOLEAN,
+	JS_CNUMBER,
+	JS_CSTRING,
+	JS_CREGEXP,
+	JS_CDATE,
+	JS_CMATH,
+	JS_CJSON,
+	JS_CARGUMENTS,
+	JS_CITERATOR,
+	JS_CUSERDATA,
+};
+
+/*
+	Short strings abuse the js_Value struct. By putting the type tag in the
+	last byte, and using 0 as the tag for short strings, we can use the
+	entire js_Value as string storage by letting the type tag serve double
+	purpose as the string zero terminator.
+*/
+
+struct js_Value
+{
+	union {
+		int boolean;
+		double number;
+		char shrstr[8];
+		const char *litstr;
+		js_String *memstr;
+		js_Object *object;
+	} u;
+	char pad[7]; /* extra storage for shrstr */
+	char type; /* type tag and zero terminator for shrstr */
+};
+
+struct js_String
+{
+	js_String *gcnext;
+	char gcmark;
+	char p[1];
+};
+
+struct js_Regexp
+{
+	void *prog;
+	char *source;
+	unsigned short flags;
+	unsigned short last;
+};
+
+struct js_Object
+{
+	enum js_Class type;
+	int extensible;
+	js_Property *properties;
+	int count; /* number of properties, for array sparseness check */
+	js_Object *prototype;
+	union {
+		int boolean;
+		double number;
+		struct {
+			int length;
+			char *string;
+			char shrstr[16];
+		} s;
+		struct {
+			int length; /* actual length */
+			int simple; /* true if array has only non-sparse array properties */
+			int flat_length; /* used length of simple array part */
+			int flat_capacity; /* allocated length of simple array part */
+			js_Value *array;
+		} a;
+		struct {
+			js_Function *function;
+			js_Environment *scope;
+		} f;
+		struct {
+			const char *name;
+			js_CFunction function;
+			js_CFunction constructor;
+			int length;
+			void *data;
+			js_Finalize finalize;
+		} c;
+		js_Regexp r;
+		struct {
+			js_Object *target;
+			int i, n; /* for array part */
+			js_Iterator *head, *current; /* for object part */
+		} iter;
+		struct {
+			const char *tag;
+			void *data;
+			js_HasProperty has;
+			js_Put put;
+			js_Delete delete;
+			js_Finalize finalize;
+		} user;
+	} u;
+	js_Object *gcnext; /* allocation list */
+	js_Object *gcroot; /* scan list */
+	int gcmark;
+};
+
+struct js_Property
+{
+	js_Property *left, *right;
+	int level;
+	int atts;
+	js_Value value;
+	js_Object *getter;
+	js_Object *setter;
+	char name[1];
+};
+
+struct js_Iterator
+{
+	js_Iterator *next;
+	char name[1];
+};
+
+struct js_Environment
+{
+	js_Environment *outer;
+	js_Object *variables;
+
+	js_Environment *gcnext;
+	int gcmark;
+};
+
+/* jsrun.c */
+js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer);
+js_String *jsV_newmemstring(js_State *J, const char *s, int n);
+js_Value *js_tovalue(js_State *J, int idx);
+void js_toprimitive(js_State *J, int idx, int hint);
+js_Object *js_toobject(js_State *J, int idx);
+void js_pushvalue(js_State *J, js_Value v);
+void js_pushobject(js_State *J, js_Object *v);
+void jsR_unflattenarray(js_State *J, js_Object *obj);
+
+/* jsvalue.c */
+int jsV_toboolean(js_State *J, js_Value *v);
+double jsV_tonumber(js_State *J, js_Value *v);
+double jsV_tointeger(js_State *J, js_Value *v);
+const char *jsV_tostring(js_State *J, js_Value *v);
+js_Object *jsV_toobject(js_State *J, js_Value *v);
+void jsV_toprimitive(js_State *J, js_Value *v, int preferred);
+
+const char *js_itoa(char *buf, int a);
+double js_stringtofloat(const char *s, char **ep);
+int jsV_numbertointeger(double n);
+int jsV_numbertoint32(double n);
+unsigned int jsV_numbertouint32(double n);
+short jsV_numbertoint16(double n);
+unsigned short jsV_numbertouint16(double n);
+const char *jsV_numbertostring(js_State *J, char buf[32], double number);
+double jsV_stringtonumber(js_State *J, const char *string);
+
+/* jsproperty.c */
+js_Object *jsV_newobject(js_State *J, enum js_Class type, js_Object *prototype);
+js_Property *jsV_getownproperty(js_State *J, js_Object *obj, const char *name);
+js_Property *jsV_getpropertyx(js_State *J, js_Object *obj, const char *name, int *own);
+js_Property *jsV_getproperty(js_State *J, js_Object *obj, const char *name);
+js_Property *jsV_setproperty(js_State *J, js_Object *obj, const char *name);
+js_Property *jsV_nextproperty(js_State *J, js_Object *obj, const char *name);
+void jsV_delproperty(js_State *J, js_Object *obj, const char *name);
+
+js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own);
+const char *jsV_nextiterator(js_State *J, js_Object *iter);
+
+void jsV_resizearray(js_State *J, js_Object *obj, int newlen);
+
+void jsV_unflattenarray(js_State *J, js_Object *obj);
+void jsV_growarray(js_State *J, js_Object *obj);
+
+/* jsdump.c */
+void js_dumpobject(js_State *J, js_Object *obj);
+void js_dumpvalue(js_State *J, js_Value v);
+
+/* Lexer */
+
+enum
+{
+	TK_IDENTIFIER = 256,
+	TK_NUMBER,
+	TK_STRING,
+	TK_REGEXP,
+
+	/* multi-character punctuators */
+	TK_LE,
+	TK_GE,
+	TK_EQ,
+	TK_NE,
+	TK_STRICTEQ,
+	TK_STRICTNE,
+	TK_SHL,
+	TK_SHR,
+	TK_USHR,
+	TK_AND,
+	TK_OR,
+	TK_ADD_ASS,
+	TK_SUB_ASS,
+	TK_MUL_ASS,
+	TK_DIV_ASS,
+	TK_MOD_ASS,
+	TK_SHL_ASS,
+	TK_SHR_ASS,
+	TK_USHR_ASS,
+	TK_AND_ASS,
+	TK_OR_ASS,
+	TK_XOR_ASS,
+	TK_INC,
+	TK_DEC,
+
+	/* keywords */
+	TK_BREAK,
+	TK_CASE,
+	TK_CATCH,
+	TK_CONTINUE,
+	TK_DEBUGGER,
+	TK_DEFAULT,
+	TK_DELETE,
+	TK_DO,
+	TK_ELSE,
+	TK_FALSE,
+	TK_FINALLY,
+	TK_FOR,
+	TK_FUNCTION,
+	TK_IF,
+	TK_IN,
+	TK_INSTANCEOF,
+	TK_NEW,
+	TK_NULL,
+	TK_RETURN,
+	TK_SWITCH,
+	TK_THIS,
+	TK_THROW,
+	TK_TRUE,
+	TK_TRY,
+	TK_TYPEOF,
+	TK_VAR,
+	TK_VOID,
+	TK_WHILE,
+	TK_WITH,
+};
+
+int jsY_iswhite(int c);
+int jsY_isnewline(int c);
+int jsY_ishex(int c);
+int jsY_tohex(int c);
+
+const char *jsY_tokenstring(int token);
+int jsY_findword(const char *s, const char **list, int num);
+
+void jsY_initlex(js_State *J, const char *filename, const char *source);
+int jsY_lex(js_State *J);
+int jsY_lexjson(js_State *J);
+
+/* Parser */
+
+enum js_AstType
+{
+	AST_LIST,
+	AST_FUNDEC,
+	AST_IDENTIFIER,
+
+	EXP_IDENTIFIER,
+	EXP_NUMBER,
+	EXP_STRING,
+	EXP_REGEXP,
+
+	/* literals */
+	EXP_UNDEF, /* for array elisions */
+	EXP_NULL,
+	EXP_TRUE,
+	EXP_FALSE,
+	EXP_THIS,
+
+	EXP_ARRAY,
+	EXP_OBJECT,
+	EXP_PROP_VAL,
+	EXP_PROP_GET,
+	EXP_PROP_SET,
+
+	EXP_FUN,
+
+	/* expressions */
+	EXP_INDEX,
+	EXP_MEMBER,
+	EXP_CALL,
+	EXP_NEW,
+
+	EXP_POSTINC,
+	EXP_POSTDEC,
+
+	EXP_DELETE,
+	EXP_VOID,
+	EXP_TYPEOF,
+	EXP_PREINC,
+	EXP_PREDEC,
+	EXP_POS,
+	EXP_NEG,
+	EXP_BITNOT,
+	EXP_LOGNOT,
+
+	EXP_MOD,
+	EXP_DIV,
+	EXP_MUL,
+	EXP_SUB,
+	EXP_ADD,
+	EXP_USHR,
+	EXP_SHR,
+	EXP_SHL,
+	EXP_IN,
+	EXP_INSTANCEOF,
+	EXP_GE,
+	EXP_LE,
+	EXP_GT,
+	EXP_LT,
+	EXP_STRICTNE,
+	EXP_STRICTEQ,
+	EXP_NE,
+	EXP_EQ,
+	EXP_BITAND,
+	EXP_BITXOR,
+	EXP_BITOR,
+	EXP_LOGAND,
+	EXP_LOGOR,
+
+	EXP_COND,
+
+	EXP_ASS,
+	EXP_ASS_MUL,
+	EXP_ASS_DIV,
+	EXP_ASS_MOD,
+	EXP_ASS_ADD,
+	EXP_ASS_SUB,
+	EXP_ASS_SHL,
+	EXP_ASS_SHR,
+	EXP_ASS_USHR,
+	EXP_ASS_BITAND,
+	EXP_ASS_BITXOR,
+	EXP_ASS_BITOR,
+
+	EXP_COMMA,
+
+	EXP_VAR, /* var initializer */
+
+	/* statements */
+	STM_BLOCK,
+	STM_EMPTY,
+	STM_VAR,
+	STM_IF,
+	STM_DO,
+	STM_WHILE,
+	STM_FOR,
+	STM_FOR_VAR,
+	STM_FOR_IN,
+	STM_FOR_IN_VAR,
+	STM_CONTINUE,
+	STM_BREAK,
+	STM_RETURN,
+	STM_WITH,
+	STM_SWITCH,
+	STM_THROW,
+	STM_TRY,
+	STM_DEBUGGER,
+
+	STM_LABEL,
+	STM_CASE,
+	STM_DEFAULT,
+};
+
+typedef struct js_JumpList js_JumpList;
+
+struct js_JumpList
+{
+	enum js_AstType type;
+	int inst;
+	js_JumpList *next;
+};
+
+struct js_Ast
+{
+	enum js_AstType type;
+	int line;
+	js_Ast *parent, *a, *b, *c, *d;
+	double number;
+	const char *string;
+	js_JumpList *jumps; /* list of break/continue jumps to patch */
+	int casejump; /* for switch case clauses */
+	js_Ast *gcnext; /* next in alloc list */
+};
+
+js_Ast *jsP_parsefunction(js_State *J, const char *filename, const char *params, const char *body);
+js_Ast *jsP_parse(js_State *J, const char *filename, const char *source);
+void jsP_freeparse(js_State *J);
+
+const char *jsP_aststring(enum js_AstType type);
+void jsP_dumpsyntax(js_State *J, js_Ast *prog, int minify);
+void jsP_dumplist(js_State *J, js_Ast *prog);
+
+/* Compiler */
+
+enum js_OpCode
+{
+	OP_POP,		/* A -- */
+	OP_DUP,		/* A -- A A */
+	OP_DUP2,	/* A B -- A B A B */
+	OP_ROT2,	/* A B -- B A */
+	OP_ROT3,	/* A B C -- C A B */
+	OP_ROT4,	/* A B C D -- D A B C */
+
+	OP_INTEGER,	/* -K- (number-32768) */
+	OP_NUMBER,	/* -N- <number> */
+	OP_STRING,	/* -S- <string> */
+	OP_CLOSURE,	/* -F- <closure> */
+
+	OP_NEWARRAY,
+	OP_NEWOBJECT,
+	OP_NEWREGEXP,	/* -S,opts- <regexp> */
+
+	OP_UNDEF,
+	OP_NULL,
+	OP_TRUE,
+	OP_FALSE,
+
+	OP_THIS,
+	OP_CURRENT,	/* currently executing function object */
+
+	OP_GETLOCAL,	/* -K- <value> */
+	OP_SETLOCAL,	/* <value> -K- <value> */
+	OP_DELLOCAL,	/* -K- false */
+
+	OP_HASVAR,	/* -S- ( <value> | undefined ) */
+	OP_GETVAR,	/* -S- <value> */
+	OP_SETVAR,	/* <value> -S- <value> */
+	OP_DELVAR,	/* -S- <success> */
+
+	OP_IN,		/* <name> <obj> -- <exists?> */
+
+	OP_INITARRAY,	/* <obj> <val> -- <obj> */
+	OP_INITPROP,	/* <obj> <key> <val> -- <obj> */
+	OP_INITGETTER,	/* <obj> <key> <closure> -- <obj> */
+	OP_INITSETTER,	/* <obj> <key> <closure> -- <obj> */
+
+	OP_GETPROP,	/* <obj> <name> -- <value> */
+	OP_GETPROP_S,	/* <obj> -S- <value> */
+	OP_SETPROP,	/* <obj> <name> <value> -- <value> */
+	OP_SETPROP_S,	/* <obj> <value> -S- <value> */
+	OP_DELPROP,	/* <obj> <name> -- <success> */
+	OP_DELPROP_S,	/* <obj> -S- <success> */
+
+	OP_ITERATOR,	/* <obj> -- <iobj> */
+	OP_NEXTITER,	/* <iobj> -- ( <iobj> <name> true | false ) */
+
+	OP_EVAL,	/* <args...> -(numargs)- <returnvalue> */
+	OP_CALL,	/* <closure> <this> <args...> -(numargs)- <returnvalue> */
+	OP_NEW,		/* <closure> <args...> -(numargs)- <returnvalue> */
+
+	OP_TYPEOF,
+	OP_POS,
+	OP_NEG,
+	OP_BITNOT,
+	OP_LOGNOT,
+	OP_INC,		/* <x> -- ToNumber(x)+1 */
+	OP_DEC,		/* <x> -- ToNumber(x)-1 */
+	OP_POSTINC,	/* <x> -- ToNumber(x)+1 ToNumber(x) */
+	OP_POSTDEC,	/* <x> -- ToNumber(x)-1 ToNumber(x) */
+
+	OP_MUL,
+	OP_DIV,
+	OP_MOD,
+	OP_ADD,
+	OP_SUB,
+	OP_SHL,
+	OP_SHR,
+	OP_USHR,
+	OP_LT,
+	OP_GT,
+	OP_LE,
+	OP_GE,
+	OP_EQ,
+	OP_NE,
+	OP_STRICTEQ,
+	OP_STRICTNE,
+	OP_JCASE,
+	OP_BITAND,
+	OP_BITXOR,
+	OP_BITOR,
+
+	OP_INSTANCEOF,
+
+	OP_THROW,
+
+	OP_TRY,		/* -ADDR- /jump/ or -ADDR- <exception> */
+	OP_ENDTRY,
+
+	OP_CATCH,	/* push scope chain with exception variable */
+	OP_ENDCATCH,
+
+	OP_WITH,
+	OP_ENDWITH,
+
+	OP_DEBUGGER,
+	OP_JUMP,
+	OP_JTRUE,
+	OP_JFALSE,
+	OP_RETURN,
+};
+
+struct js_Function
+{
+	const char *name;
+	int script;
+	int lightweight;
+	int strict;
+	int arguments;
+	int numparams;
+
+	js_Instruction *code;
+	int codecap, codelen;
+
+	js_Function **funtab;
+	int funcap, funlen;
+
+	const char **vartab;
+	int varcap, varlen;
+
+	const char *filename;
+	int line, lastline;
+
+	js_Function *gcnext;
+	int gcmark;
+};
+
+js_Function *jsC_compilefunction(js_State *J, js_Ast *prog);
+js_Function *jsC_compilescript(js_State *J, js_Ast *prog, int default_strict);
+const char *jsC_opcodestring(enum js_OpCode opcode);
+void jsC_dumpfunction(js_State *J, js_Function *fun);
+
+/* Builtins */
+
+void jsB_init(js_State *J);
+void jsB_initobject(js_State *J);
+void jsB_initarray(js_State *J);
+void jsB_initfunction(js_State *J);
+void jsB_initboolean(js_State *J);
+void jsB_initnumber(js_State *J);
+void jsB_initstring(js_State *J);
+void jsB_initregexp(js_State *J);
+void jsB_initerror(js_State *J);
+void jsB_initmath(js_State *J);
+void jsB_initjson(js_State *J);
+void jsB_initdate(js_State *J);
+
+void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n);
+void jsB_propn(js_State *J, const char *name, double number);
+void jsB_props(js_State *J, const char *name, const char *string);
+
 #endif
--- a/jslex.c
+++ b/jslex.c
@@ -1,5 +1,4 @@
 #include "jsi.h"
-#include "jslex.h"
 #include "utf.h"
 
 JS_NORETURN static void jsY_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
--- a/jslex.h
+++ /dev/null
@@ -1,81 +1,0 @@
-#ifndef js_lex_h
-#define js_lex_h
-
-enum
-{
-	TK_IDENTIFIER = 256,
-	TK_NUMBER,
-	TK_STRING,
-	TK_REGEXP,
-
-	/* multi-character punctuators */
-	TK_LE,
-	TK_GE,
-	TK_EQ,
-	TK_NE,
-	TK_STRICTEQ,
-	TK_STRICTNE,
-	TK_SHL,
-	TK_SHR,
-	TK_USHR,
-	TK_AND,
-	TK_OR,
-	TK_ADD_ASS,
-	TK_SUB_ASS,
-	TK_MUL_ASS,
-	TK_DIV_ASS,
-	TK_MOD_ASS,
-	TK_SHL_ASS,
-	TK_SHR_ASS,
-	TK_USHR_ASS,
-	TK_AND_ASS,
-	TK_OR_ASS,
-	TK_XOR_ASS,
-	TK_INC,
-	TK_DEC,
-
-	/* keywords */
-	TK_BREAK,
-	TK_CASE,
-	TK_CATCH,
-	TK_CONTINUE,
-	TK_DEBUGGER,
-	TK_DEFAULT,
-	TK_DELETE,
-	TK_DO,
-	TK_ELSE,
-	TK_FALSE,
-	TK_FINALLY,
-	TK_FOR,
-	TK_FUNCTION,
-	TK_IF,
-	TK_IN,
-	TK_INSTANCEOF,
-	TK_NEW,
-	TK_NULL,
-	TK_RETURN,
-	TK_SWITCH,
-	TK_THIS,
-	TK_THROW,
-	TK_TRUE,
-	TK_TRY,
-	TK_TYPEOF,
-	TK_VAR,
-	TK_VOID,
-	TK_WHILE,
-	TK_WITH,
-};
-
-int jsY_iswhite(int c);
-int jsY_isnewline(int c);
-int jsY_ishex(int c);
-int jsY_tohex(int c);
-
-const char *jsY_tokenstring(int token);
-int jsY_findword(const char *s, const char **list, int num);
-
-void jsY_initlex(js_State *J, const char *filename, const char *source);
-int jsY_lex(js_State *J);
-int jsY_lexjson(js_State *J);
-
-#endif
--- a/jsmath.c
+++ b/jsmath.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 
 #if defined(_MSC_VER) && (_MSC_VER < 1700) /* VS2012 has stdint.h */
 typedef unsigned int uint32_t;
--- a/jsnumber.c
+++ b/jsnumber.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 
 #if defined(_MSC_VER) && (_MSC_VER < 1700) /* VS2012 has stdint.h */
 typedef unsigned __int64 uint64_t;
--- a/jsobject.c
+++ b/jsobject.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 
 static void jsB_new_Object(js_State *J)
 {
--- a/json.c
+++ b/json.c
@@ -1,8 +1,4 @@
 #include "jsi.h"
-#include "jslex.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
-
 #include "utf.h"
 
 int js_isnumberobject(js_State *J, int idx)
--- a/jsparse.c
+++ b/jsparse.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jslex.h"
-#include "jsparse.h"
 
 #define LIST(h)			jsP_newnode(J, AST_LIST, 0, h, 0, 0, 0)
 
--- a/jsparse.h
+++ /dev/null
@@ -1,146 +1,0 @@
-#ifndef js_parse_h
-#define js_parse_h
-
-enum js_AstType
-{
-	AST_LIST,
-	AST_FUNDEC,
-	AST_IDENTIFIER,
-
-	EXP_IDENTIFIER,
-	EXP_NUMBER,
-	EXP_STRING,
-	EXP_REGEXP,
-
-	/* literals */
-	EXP_UNDEF, /* for array elisions */
-	EXP_NULL,
-	EXP_TRUE,
-	EXP_FALSE,
-	EXP_THIS,
-
-	EXP_ARRAY,
-	EXP_OBJECT,
-	EXP_PROP_VAL,
-	EXP_PROP_GET,
-	EXP_PROP_SET,
-
-	EXP_FUN,
-
-	/* expressions */
-	EXP_INDEX,
-	EXP_MEMBER,
-	EXP_CALL,
-	EXP_NEW,
-
-	EXP_POSTINC,
-	EXP_POSTDEC,
-
-	EXP_DELETE,
-	EXP_VOID,
-	EXP_TYPEOF,
-	EXP_PREINC,
-	EXP_PREDEC,
-	EXP_POS,
-	EXP_NEG,
-	EXP_BITNOT,
-	EXP_LOGNOT,
-
-	EXP_MOD,
-	EXP_DIV,
-	EXP_MUL,
-	EXP_SUB,
-	EXP_ADD,
-	EXP_USHR,
-	EXP_SHR,
-	EXP_SHL,
-	EXP_IN,
-	EXP_INSTANCEOF,
-	EXP_GE,
-	EXP_LE,
-	EXP_GT,
-	EXP_LT,
-	EXP_STRICTNE,
-	EXP_STRICTEQ,
-	EXP_NE,
-	EXP_EQ,
-	EXP_BITAND,
-	EXP_BITXOR,
-	EXP_BITOR,
-	EXP_LOGAND,
-	EXP_LOGOR,
-
-	EXP_COND,
-
-	EXP_ASS,
-	EXP_ASS_MUL,
-	EXP_ASS_DIV,
-	EXP_ASS_MOD,
-	EXP_ASS_ADD,
-	EXP_ASS_SUB,
-	EXP_ASS_SHL,
-	EXP_ASS_SHR,
-	EXP_ASS_USHR,
-	EXP_ASS_BITAND,
-	EXP_ASS_BITXOR,
-	EXP_ASS_BITOR,
-
-	EXP_COMMA,
-
-	EXP_VAR, /* var initializer */
-
-	/* statements */
-	STM_BLOCK,
-	STM_EMPTY,
-	STM_VAR,
-	STM_IF,
-	STM_DO,
-	STM_WHILE,
-	STM_FOR,
-	STM_FOR_VAR,
-	STM_FOR_IN,
-	STM_FOR_IN_VAR,
-	STM_CONTINUE,
-	STM_BREAK,
-	STM_RETURN,
-	STM_WITH,
-	STM_SWITCH,
-	STM_THROW,
-	STM_TRY,
-	STM_DEBUGGER,
-
-	STM_LABEL,
-	STM_CASE,
-	STM_DEFAULT,
-};
-
-typedef struct js_JumpList js_JumpList;
-
-struct js_JumpList
-{
-	enum js_AstType type;
-	int inst;
-	js_JumpList *next;
-};
-
-struct js_Ast
-{
-	enum js_AstType type;
-	int line;
-	js_Ast *parent, *a, *b, *c, *d;
-	double number;
-	const char *string;
-	js_JumpList *jumps; /* list of break/continue jumps to patch */
-	int casejump; /* for switch case clauses */
-	js_Ast *gcnext; /* next in alloc list */
-};
-
-js_Ast *jsP_parsefunction(js_State *J, const char *filename, const char *params, const char *body);
-js_Ast *jsP_parse(js_State *J, const char *filename, const char *source);
-void jsP_freeparse(js_State *J);
-
-const char *jsP_aststring(enum js_AstType type);
-void jsP_dumpsyntax(js_State *J, js_Ast *prog, int minify);
-void jsP_dumplist(js_State *J, js_Ast *prog);
-
-#endif
--- a/jsproperty.c
+++ b/jsproperty.c
@@ -1,5 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
 
 #include <assert.h>
 
--- a/jsregexp.c
+++ b/jsregexp.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 #include "regexp.h"
 
 static char *escaperegexp(js_State *J, const char *pattern) {
--- a/jsrepr.c
+++ b/jsrepr.c
@@ -1,8 +1,4 @@
 #include "jsi.h"
-#include "jslex.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
-#include "jscompile.h"
 #include "utf.h"
 
 static void reprvalue(js_State *J, js_Buffer **sb);
--- a/jsrun.c
+++ b/jsrun.c
@@ -1,8 +1,4 @@
 #include "jsi.h"
-#include "jscompile.h"
-#include "jsvalue.h"
-#include "jsrun.h"
-
 #include "utf.h"
 
 #include <assert.h>
--- a/jsrun.h
+++ /dev/null
@@ -1,15 +1,0 @@
-#ifndef js_run_h
-#define js_run_h
-
-js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer);
-
-struct js_Environment
-{
-	js_Environment *outer;
-	js_Object *variables;
-
-	js_Environment *gcnext;
-	int gcmark;
-};
-
-#endif
--- a/jsstate.c
+++ b/jsstate.c
@@ -1,9 +1,4 @@
 #include "jsi.h"
-#include "jsparse.h"
-#include "jscompile.h"
-#include "jsvalue.h"
-#include "jsrun.h"
-#include "jsbuiltin.h"
 
 #include <assert.h>
 #include <errno.h>
--- a/jsstring.c
+++ b/jsstring.c
@@ -1,6 +1,4 @@
 #include "jsi.h"
-#include "jsvalue.h"
-#include "jsbuiltin.h"
 #include "utf.h"
 #include "regexp.h"
 
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -1,7 +1,4 @@
 #include "jsi.h"
-#include "jslex.h"
-#include "jscompile.h"
-#include "jsvalue.h"
 #include "utf.h"
 
 #define JSV_ISSTRING(v) (v->type==JS_TSHRSTR || v->type==JS_TMEMSTR || v->type==JS_TLITSTR)
--- a/jsvalue.h
+++ /dev/null
@@ -1,199 +1,0 @@
-#ifndef js_value_h
-#define js_value_h
-
-typedef struct js_Property js_Property;
-typedef struct js_Iterator js_Iterator;
-
-/* Hint to ToPrimitive() */
-enum {
-	JS_HNONE,
-	JS_HNUMBER,
-	JS_HSTRING
-};
-
-enum js_Type {
-	JS_TSHRSTR, /* type tag doubles as string zero-terminator */
-	JS_TUNDEFINED,
-	JS_TNULL,
-	JS_TBOOLEAN,
-	JS_TNUMBER,
-	JS_TLITSTR,
-	JS_TMEMSTR,
-	JS_TOBJECT,
-};
-
-enum js_Class {
-	JS_COBJECT,
-	JS_CARRAY,
-	JS_CFUNCTION,
-	JS_CSCRIPT, /* function created from global/eval code */
-	JS_CCFUNCTION, /* built-in function */
-	JS_CERROR,
-	JS_CBOOLEAN,
-	JS_CNUMBER,
-	JS_CSTRING,
-	JS_CREGEXP,
-	JS_CDATE,
-	JS_CMATH,
-	JS_CJSON,
-	JS_CARGUMENTS,
-	JS_CITERATOR,
-	JS_CUSERDATA,
-};
-
-/*
-	Short strings abuse the js_Value struct. By putting the type tag in the
-	last byte, and using 0 as the tag for short strings, we can use the
-	entire js_Value as string storage by letting the type tag serve double
-	purpose as the string zero terminator.
-*/
-
-struct js_Value
-{
-	union {
-		int boolean;
-		double number;
-		char shrstr[8];
-		const char *litstr;
-		js_String *memstr;
-		js_Object *object;
-	} u;
-	char pad[7]; /* extra storage for shrstr */
-	char type; /* type tag and zero terminator for shrstr */
-};
-
-struct js_String
-{
-	js_String *gcnext;
-	char gcmark;
-	char p[1];
-};
-
-struct js_Regexp
-{
-	void *prog;
-	char *source;
-	unsigned short flags;
-	unsigned short last;
-};
-
-struct js_Object
-{
-	enum js_Class type;
-	int extensible;
-	js_Property *properties;
-	int count; /* number of properties, for array sparseness check */
-	js_Object *prototype;
-	union {
-		int boolean;
-		double number;
-		struct {
-			int length;
-			char *string;
-			char shrstr[16];
-		} s;
-		struct {
-			int length; /* actual length */
-			int simple; /* true if array has only non-sparse array properties */
-			int flat_length; /* used length of simple array part */
-			int flat_capacity; /* allocated length of simple array part */
-			js_Value *array;
-		} a;
-		struct {
-			js_Function *function;
-			js_Environment *scope;
-		} f;
-		struct {
-			const char *name;
-			js_CFunction function;
-			js_CFunction constructor;
-			int length;
-			void *data;
-			js_Finalize finalize;
-		} c;
-		js_Regexp r;
-		struct {
-			js_Object *target;
-			int i, n; /* for array part */
-			js_Iterator *head, *current; /* for object part */
-		} iter;
-		struct {
-			const char *tag;
-			void *data;
-			js_HasProperty has;
-			js_Put put;
-			js_Delete delete;
-			js_Finalize finalize;
-		} user;
-	} u;
-	js_Object *gcnext; /* allocation list */
-	js_Object *gcroot; /* scan list */
-	int gcmark;
-};
-
-struct js_Property
-{
-	js_Property *left, *right;
-	int level;
-	int atts;
-	js_Value value;
-	js_Object *getter;
-	js_Object *setter;
-	char name[1];
-};
-
-struct js_Iterator
-{
-	js_Iterator *next;
-	char name[1];
-};
-
-/* jsrun.c */
-js_String *jsV_newmemstring(js_State *J, const char *s, int n);
-js_Value *js_tovalue(js_State *J, int idx);
-void js_toprimitive(js_State *J, int idx, int hint);
-js_Object *js_toobject(js_State *J, int idx);
-void js_pushvalue(js_State *J, js_Value v);
-void js_pushobject(js_State *J, js_Object *v);
-void jsR_unflattenarray(js_State *J, js_Object *obj);
-
-/* jsvalue.c */
-int jsV_toboolean(js_State *J, js_Value *v);
-double jsV_tonumber(js_State *J, js_Value *v);
-double jsV_tointeger(js_State *J, js_Value *v);
-const char *jsV_tostring(js_State *J, js_Value *v);
-js_Object *jsV_toobject(js_State *J, js_Value *v);
-void jsV_toprimitive(js_State *J, js_Value *v, int preferred);
-
-const char *js_itoa(char *buf, int a);
-double js_stringtofloat(const char *s, char **ep);
-int jsV_numbertointeger(double n);
-int jsV_numbertoint32(double n);
-unsigned int jsV_numbertouint32(double n);
-short jsV_numbertoint16(double n);
-unsigned short jsV_numbertouint16(double n);
-const char *jsV_numbertostring(js_State *J, char buf[32], double number);
-double jsV_stringtonumber(js_State *J, const char *string);
-
-/* jsproperty.c */
-js_Object *jsV_newobject(js_State *J, enum js_Class type, js_Object *prototype);
-js_Property *jsV_getownproperty(js_State *J, js_Object *obj, const char *name);
-js_Property *jsV_getpropertyx(js_State *J, js_Object *obj, const char *name, int *own);
-js_Property *jsV_getproperty(js_State *J, js_Object *obj, const char *name);
-js_Property *jsV_setproperty(js_State *J, js_Object *obj, const char *name);
-js_Property *jsV_nextproperty(js_State *J, js_Object *obj, const char *name);
-void jsV_delproperty(js_State *J, js_Object *obj, const char *name);
-
-js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own);
-const char *jsV_nextiterator(js_State *J, js_Object *iter);
-
-void jsV_resizearray(js_State *J, js_Object *obj, int newlen);
-
-void jsV_unflattenarray(js_State *J, js_Object *obj);
-void jsV_growarray(js_State *J, js_Object *obj);
-
-/* jsdump.c */
-void js_dumpobject(js_State *J, js_Object *obj);
-void js_dumpvalue(js_State *J, js_Value v);
-
-#endif
--- a/pp.c
+++ b/pp.c
@@ -8,7 +8,6 @@
 #include <stdio.h>
 
 #include "jsi.h"
-#include "jsparse.h"
 
 static void js_ppstring(js_State *J, const char *filename, const char *source, int minify)
 {