2 * JavaScript interpreter main glue.
3 * Copyright (c) 1998-1999 New Generation Software (NGS) Oy
5 * Author: Markku Rossi <mtr@ngs.fi>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/src/js.c,v $
34 * Types and definitions.
37 /* Context for js_global_method_stub. */
38 struct js_global_method_context_st
40 JSGlobalMethodProc proc
;
46 typedef struct js_global_method_context_st JSGlobalMethodContext
;
48 /* Context for user I/O function streams. */
49 struct js_user_io_func_ctx_st
56 typedef struct js_user_io_func_ctx_st JSUserIOFuncCtx
;
58 struct js_method_reg_st
66 typedef struct js_method_reg_st JSMethodReg
;
68 struct js_property_reg_st
73 JSPropertyProc property
;
76 typedef struct js_property_reg_st JSPropertyReg
;
78 /* The class handle. */
85 unsigned int no_auto_destroy
: 1;
86 unsigned int interned
: 1;
89 JSFreeProc class_context_destructor
;
91 JSConstructor constructor
;
93 unsigned int num_methods
;
96 unsigned int num_properties
;
97 JSPropertyReg
*properties
;
100 /* Object instance context. */
101 struct js_object_instance_ctx_st
103 void *instance_context
;
104 JSFreeProc instance_context_destructor
;
107 typedef struct js_object_instance_ctx_st JSObjectInstanceCtx
;
111 * Prototypes for static functions.
114 /* The module for JS' core global methods. */
115 static void js_core_globals (JSInterpPtr interp
);
118 * Helper function to evaluate source <source> with compiler function
119 * <compiler_function>.
121 static int js_eval_source (JSInterpPtr interp
, JSNode
*source
,
122 char *compiler_function
);
125 * Helper function to compile source <source> with compiler function
126 * <compiler_function>. If <assembler_file> is not NULL, the
127 * assembler listing of the compilation is saved to that file. If
128 * <byte_code_file> is not NULL, the byte_code data is saved to that
129 * file. If <bc_return> is not NULL, the resulting byte_code data is
130 * returned in it as a JavaScript string node.
132 static int js_compile_source (JSInterpPtr interp
, JSNode
*source
,
133 char *compiler_function
, char *assembler_file
,
134 char *byte_code_file
, JSNode
*bc_return
);
137 * The stub function for global methods, created with the
138 * js_create_global_method() API function.
140 static void js_global_method_stub (JSVirtualMachine
*vm
,
141 JSBuiltinInfo
*builtin_info
,
142 void *instance_context
,
143 JSNode
*result_return
,
147 * Destructor for the global methods, created with the
148 * js_create_global_method() API function.
150 static void js_global_method_delete (JSBuiltinInfo
*builtin_info
,
151 void *instance_context
);
153 static JSIOStream
*iostream_iofunc (JSIOFunc func
, void *context
,
154 int readp
, int writep
);
169 js_init_default_options (JSInterpOptions
*options
)
171 memset (options
, 0, sizeof (*options
));
173 options
->stack_size
= 2048;
174 options
->dispatch_method
= JS_VM_DISPATCH_JUMPS
;
176 options
->warn_undef
= 1;
178 options
->optimize_peephole
= 1;
179 options
->optimize_jumps_to_jumps
= 1;
181 options
->fd_count
= (unsigned long) -1;
186 js_create_interp (JSInterpOptions
*options
)
188 JSInterpPtr interp
= NULL
;
190 JSInterpOptions default_options
;
191 JSIOStream
*s_stdin
= NULL
;
192 JSIOStream
*s_stdout
= NULL
;
193 JSIOStream
*s_stderr
= NULL
;
196 * Sanity check to assure that the js.h and jsint.h APIs share a
197 * same view to the world.
199 assert (sizeof (JSNode
) == sizeof (JSType
));
201 interp
= js_calloc (NULL
, 1, sizeof (*interp
));
207 js_init_default_options (&default_options
);
208 options
= &default_options
;
211 memcpy (&interp
->options
, options
, sizeof (*options
));
213 /* The default system streams. */
215 if (options
->s_stdin
)
216 s_stdin
= iostream_iofunc (options
->s_stdin
, options
->s_context
, 1, 0);
218 s_stdin
= js_iostream_file (stdin
, 1, 0, 0);
223 if (options
->s_stdout
)
224 s_stdout
= iostream_iofunc (options
->s_stdout
, options
->s_context
, 0, 1);
226 s_stdout
= js_iostream_file (stdout
, 0, 1, 0);
228 if (s_stdout
== NULL
)
230 s_stdout
->autoflush
= 1;
232 if (options
->s_stderr
)
233 s_stderr
= iostream_iofunc (options
->s_stderr
, options
->s_context
, 0, 1);
235 s_stderr
= js_iostream_file (stderr
, 0, 1, 0);
237 if (s_stderr
== NULL
)
239 s_stderr
->autoflush
= 1;
241 /* Create virtual machine. */
242 interp
->vm
= js_vm_create (options
->stack_size
,
243 options
->dispatch_method
,
245 options
->stacktrace_on_error
,
246 s_stdin
, s_stdout
, s_stderr
);
247 if (interp
->vm
== NULL
)
250 /* Set some options. */
251 interp
->vm
->warn_undef
= options
->warn_undef
;
253 /* Set the security options. */
255 if (options
->secure_builtin_file
)
256 interp
->vm
->security
|= JS_VM_SECURE_FILE
;
257 if (options
->secure_builtin_system
)
258 interp
->vm
->security
|= JS_VM_SECURE_SYSTEM
;
260 /* Set the event hook. */
261 interp
->vm
->hook
= options
->hook
;
262 interp
->vm
->hook_context
= options
->hook_context
;
263 interp
->vm
->hook_operand_count_trigger
= options
->hook_operand_count_trigger
;
265 /* The file descriptor limit. */
266 interp
->vm
->fd_count
= options
->fd_count
;
268 if (!options
->no_compiler
)
272 /* Define compiler to the virtual machine. */
273 bc
= js_bc_read_data (js_compiler_bytecode
, js_compiler_bytecode_len
);
277 result
= js_vm_execute (interp
->vm
, bc
);
283 /* Initialize our extensions. */
284 if (!js_define_module (interp
, js_core_globals
))
290 #if JS_DEBUG_MEMORY_LEAKS
291 /* Let's see how much memory an empty interpreter takes. */
292 js_alloc_dump_blocks ();
293 #endif /* JS_DEBUG_MEMORY_LEAKS */
308 js_vm_destroy (interp
->vm
);
313 js_iostream_close (s_stdin
);
315 js_iostream_close (s_stdout
);
317 js_iostream_close (s_stderr
);
324 js_destroy_interp (JSInterpPtr interp
)
326 js_vm_destroy (interp
->vm
);
330 #if JS_DEBUG_MEMORY_LEAKS
331 /* Let's see how much memory we leak. */
332 js_alloc_dump_blocks ();
333 #endif /* JS_DEBUG_MEMORY_LEAKS */
339 js_error_message (JSInterpPtr interp
)
341 return interp
->vm
->error
;
346 js_result (JSInterpPtr interp
, JSType
*result_return
)
348 memcpy (result_return
, &interp
->vm
->exec_result
, sizeof (*result_return
));
353 js_eval (JSInterpPtr interp
, char *code
)
357 js_vm_make_static_string (interp
->vm
, &source
, code
, strlen (code
));
358 return js_eval_source (interp
, &source
, "JSC$compile_string");
363 js_eval_data (JSInterpPtr interp
, char *data
, unsigned int datalen
)
367 js_vm_make_static_string (interp
->vm
, &source
, data
, datalen
);
368 return js_eval_source (interp
, &source
, "JSC$compile_string");
373 js_eval_file (JSInterpPtr interp
, char *filename
)
378 cp
= strrchr (filename
, '.');
379 if (cp
&& strcmp (cp
, ".jsc") == 0)
382 result
= js_execute_byte_code_file (interp
, filename
);
384 else if (cp
&& strcmp (cp
, ".js") == 0)
387 result
= js_eval_javascript_file (interp
, filename
);
393 /* Must look into the file. */
395 fp
= fopen (filename
, "r");
400 if ((ch
= getc (fp
)) == '#')
402 /* Skip the first sh-command line. */
403 while ((ch
= getc (fp
)) != EOF
&& ch
!= '\n')
414 /* Check if we can read the file magic. */
427 /* Got it. We find a valid byte-code file magic. */
440 * If nothing else helps, we assume that the file contains JavaScript
441 * source code that must be compiled.
451 js_eval_javascript_file (JSInterpPtr interp
, char *filename
)
455 js_vm_make_static_string (interp
->vm
, &source
, filename
, strlen (filename
));
456 return js_eval_source (interp
, &source
, "JSC$compile_file");
461 js_execute_byte_code_file (JSInterpPtr interp
, char *filename
)
467 fp
= fopen (filename
, "rb");
470 /* Let's borrow vm's error buffer. */
471 sprintf (interp
->vm
->error
, "couldn't open byte-code file \"%s\": %s",
472 filename
, strerror (errno
));
476 bc
= js_bc_read_file (fp
);
480 /* XXX Error message. */
485 result
= js_vm_execute (interp
->vm
, bc
);
493 js_apply (JSInterpPtr interp
, char *name
, unsigned int argc
, JSType
*argv
)
499 args
= js_malloc (NULL
, (argc
+ 1) * sizeof (JSNode
));
502 sprintf (interp
->vm
->error
, "VM: out of memory");
506 /* Set the argument count. */
507 args
[0].type
= JS_INTEGER
;
508 args
[0].u
.vinteger
= argc
;
510 /* Set the arguments. */
511 for (ui
= 0; ui
< argc
; ui
++)
512 JS_COPY (&args
[ui
+ 1], (JSNode
*) &argv
[ui
]);
515 result
= js_vm_apply (interp
->vm
, name
, NULL
, argc
+ 1, args
);
524 js_compile (JSInterpPtr interp
, char *input_file
, char *assembler_file
,
525 char *byte_code_file
)
529 js_vm_make_static_string (interp
->vm
, &source
, input_file
,
530 strlen (input_file
));
531 return js_compile_source (interp
, &source
, "JSC$compile_file",
532 assembler_file
, byte_code_file
, NULL
);
537 js_compile_to_byte_code (JSInterpPtr interp
, char *input_file
,
538 unsigned char **bc_return
,
539 unsigned int *bc_len_return
)
544 js_vm_make_static_string (interp
->vm
, &source
, input_file
,
545 strlen (input_file
));
546 result
= js_compile_source (interp
, &source
, "JSC$compile_file",
547 NULL
, NULL
, &source
);
551 /* Pass the data to the caller. */
552 *bc_return
= source
.u
.vstring
->data
;
553 *bc_len_return
= source
.u
.vstring
->len
;
560 js_compile_data_to_byte_code (JSInterpPtr interp
, char *data
,
561 unsigned int datalen
,
562 unsigned char **bc_return
,
563 unsigned int *bc_len_return
)
568 js_vm_make_static_string (interp
->vm
, &source
, data
, datalen
);
569 result
= js_compile_source (interp
, &source
, "JSC$compile_string",
570 NULL
, NULL
, &source
);
574 /* Pass the data to the caller. */
575 *bc_return
= source
.u
.vstring
->data
;
576 *bc_len_return
= source
.u
.vstring
->len
;
583 js_execute_byte_code (JSInterpPtr interp
, unsigned char *bc_data
,
584 unsigned int bc_data_len
)
589 bc
= js_bc_read_data (bc_data
, bc_data_len
);
591 /* Not a valid byte-code data. */
595 result
= js_vm_execute (interp
->vm
, bc
);
605 js_class_create (void *class_context
, JSFreeProc class_context_destructor
,
606 int no_auto_destroy
, JSConstructor constructor
)
610 cls
= js_calloc (NULL
, 1, sizeof (*cls
));
614 cls
->class_context
= class_context
;
615 cls
->class_context_destructor
= class_context_destructor
;
617 cls
->no_auto_destroy
= no_auto_destroy
;
618 cls
->constructor
= constructor
;
625 js_class_destroy (JSClassPtr cls
)
630 if (cls
->class_context_destructor
)
631 (*cls
->class_context_destructor
) (cls
->class_context
);
638 js_class_context (JSClassPtr cls
)
641 return cls
->class_context
;
648 js_class_define_method (JSClassPtr cls
, char *name
, unsigned int flags
,
651 JSMethodReg
*nmethods
;
653 nmethods
= js_realloc (NULL
, cls
->methods
,
654 (cls
->num_methods
+ 1) * sizeof (JSMethodReg
));
655 if (nmethods
== NULL
)
658 cls
->methods
= nmethods
;
661 * The names are interned to symbols when the class is defined to the
665 cls
->methods
[cls
->num_methods
].name
= js_strdup (NULL
, name
);
666 if (cls
->methods
[cls
->num_methods
].name
== NULL
)
669 cls
->methods
[cls
->num_methods
].flags
= flags
;
670 cls
->methods
[cls
->num_methods
].method
= method
;
679 js_class_define_property (JSClassPtr cls
, char *name
, unsigned int flags
,
680 JSPropertyProc property
)
682 JSPropertyReg
*nprops
;
684 nprops
= js_realloc (NULL
, cls
->properties
,
685 (cls
->num_properties
+ 1) * sizeof (JSPropertyReg
));
689 cls
->properties
= nprops
;
691 cls
->properties
[cls
->num_properties
].name
= js_strdup (NULL
, name
);
692 if (cls
->properties
[cls
->num_properties
].name
== NULL
)
695 cls
->properties
[cls
->num_properties
].flags
= flags
;
696 cls
->properties
[cls
->num_properties
].property
= property
;
698 cls
->num_properties
++;
704 /* The stub functions for JSClass built-in objects. */
708 cls_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
709 void *instance_context
, JSSymbol method
, JSNode
*result_return
,
712 JSClassPtr cls
= builtin_info
->obj_context
;
713 JSObjectInstanceCtx
*ictx
= instance_context
;
715 JSMethodResult result
;
718 /* Let's see if we know the method. */
719 for (i
= 0; i
< cls
->num_methods
; i
++)
720 if (cls
->methods
[i
].sym
== method
)
725 if ((cls
->methods
[i
].flags
& JS_CF_STATIC
) == 0
726 && instance_context
== NULL
)
727 /* An instance method called from the `main' class. */
730 result
= (*cls
->methods
[i
].method
) (cls
,
732 ? ictx
->instance_context
734 cls
->interp
, args
[0].u
.vinteger
,
736 (JSType
*) result_return
,
738 if (result
== JS_ERROR
)
740 sprintf (vm
->error
, "%s.%s(): %s", cls
->name
,
741 cls
->methods
[i
].name
, msg
);
745 return JS_PROPERTY_FOUND
;
748 return JS_PROPERTY_UNKNOWN
;
753 cls_property (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
754 void *instance_context
, JSSymbol property
, int set
, JSNode
*node
)
756 JSClassPtr cls
= builtin_info
->obj_context
;
757 JSObjectInstanceCtx
*ictx
= instance_context
;
758 JSMethodResult result
;
762 /* Find the property. */
763 for (i
= 0; i
< cls
->num_properties
; i
++)
764 if (cls
->properties
[i
].sym
== property
)
770 if ((cls
->properties
[i
].flags
& JS_CF_STATIC
) == 0
771 && instance_context
== NULL
)
774 if ((cls
->properties
[i
].flags
& JS_CF_IMMUTABLE
) && set
)
776 sprintf (vm
->error
, "%s.%s: immutable property",
777 cls
->name
, cls
->properties
[i
].name
);
781 result
= (*cls
->properties
[i
].property
) (cls
,
783 ? ictx
->instance_context
786 (JSType
*) node
, msg
);
787 if (result
== JS_ERROR
)
789 sprintf (vm
->error
, "%s.%s: %s", cls
->name
,
790 cls
->properties
[i
].name
, msg
);
794 return JS_PROPERTY_FOUND
;
798 node
->type
= JS_UNDEFINED
;
800 return JS_PROPERTY_UNKNOWN
;
805 cls_new_proc (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
, JSNode
*args
,
806 JSNode
*result_return
)
808 JSClassPtr cls
= builtin_info
->obj_context
;
809 JSMethodResult result
;
811 void *instance_context
;
812 JSFreeProc instance_context_destructor
;
813 JSObjectInstanceCtx
*ictx
;
815 result
= (*cls
->constructor
) (cls
, cls
->interp
, args
[0].u
.vinteger
,
816 (JSType
*) &args
[1], &instance_context
,
817 &instance_context_destructor
,
819 if (result
== JS_ERROR
)
821 sprintf (vm
->error
, "new %s(): %s", cls
->name
, msg
);
825 ictx
= js_calloc (vm
, 1, sizeof (*ictx
));
826 ictx
->instance_context
= instance_context
;
827 ictx
->instance_context_destructor
= instance_context_destructor
;
829 js_vm_builtin_create (vm
, result_return
, builtin_info
, ictx
);
835 cls_delete_proc (JSBuiltinInfo
*builtin_info
, void *instance_context
)
837 JSObjectInstanceCtx
*ictx
= instance_context
;
841 if (ictx
->instance_context_destructor
)
842 (*ictx
->instance_context_destructor
) (ictx
->instance_context
);
849 * This is called to destroy the class handle, when there are no more
853 js_class_destructor (void *context
)
855 JSClassPtr cls
= context
;
857 if (cls
->no_auto_destroy
)
860 js_class_destroy (cls
);
865 intern_symbols (JSVirtualMachine
*vm
, JSClassPtr cls
)
869 for (i
= 0; i
< cls
->num_methods
; i
++)
870 cls
->methods
[i
].sym
= js_vm_intern (vm
, cls
->methods
[i
].name
);
872 for (i
= 0; i
< cls
->num_properties
; i
++)
873 cls
->properties
[i
].sym
= js_vm_intern (vm
, cls
->properties
[i
].name
);
879 static JSBuiltinInfo
*
880 one_builtin_info_please (JSVirtualMachine
*vm
, JSClassPtr cls
)
884 info
= js_vm_builtin_info_create (vm
);
886 info
->method_proc
= cls_method
;
887 info
->property_proc
= cls_property
;
889 if (cls
->constructor
)
891 info
->new_proc
= cls_new_proc
;
892 info
->delete_proc
= cls_delete_proc
;
895 info
->obj_context
= cls
;
896 info
->obj_context_delete
= js_class_destructor
;
903 js_define_class (JSInterpPtr interp
, JSClassPtr cls
, char *name
)
906 JSVirtualMachine
*vm
= interp
->vm
;
909 /* XXX We need a top-level here */
911 cls
->name
= js_strdup (vm
, name
);
912 cls
->interp
= interp
;
915 /* Intern the symbols and properties. */
916 intern_symbols (interp
->vm
, cls
);
918 /* Define it to the interpreter. */
920 info
= one_builtin_info_please (vm
, cls
);
922 n
= &vm
->globals
[js_vm_intern (vm
, name
)];
923 js_vm_builtin_create (vm
, n
, info
, NULL
);
930 js_instantiate_class (JSInterpPtr interp
, JSClassPtr cls
, void *ictx
,
931 JSFreeProc ictx_destructor
, JSType
*result_return
)
933 JSObjectInstanceCtx
*instance
;
934 JSVirtualMachine
*vm
= interp
->vm
;
938 /* Intern the symbols and properties. */
939 intern_symbols (vm
, cls
);
941 /* Create an instance. */
942 instance
= js_calloc (vm
, 1, sizeof (*instance
));
943 instance
->instance_context
= ictx
;
944 instance
->instance_context_destructor
= ictx_destructor
;
946 /* Create a fresh builtin info. */
947 info
= one_builtin_info_please (vm
, cls
);
950 js_vm_builtin_create (vm
, (JSNode
*) result_return
, info
, instance
);
957 js_lookup_class (JSInterpPtr interp
, char *name
)
960 JSVirtualMachine
*vm
= interp
->vm
;
962 n
= &vm
->globals
[js_vm_intern (vm
, name
)];
963 if (n
->type
!= JS_BUILTIN
)
966 if (n
->u
.vbuiltin
->info
->method_proc
!= cls_method
)
967 /* This is a wrong built-in. */
970 return (JSClassPtr
) n
->u
.vbuiltin
->info
->obj_context
;
975 js_isa (JSInterpPtr interp
, JSType
*object
, JSClassPtr cls
,
976 void **instance_context_return
)
978 JSNode
*n
= (JSNode
*) object
;
979 JSObjectInstanceCtx
*instance
;
981 if (n
->type
!= JS_BUILTIN
|| n
->u
.vbuiltin
->info
->obj_context
!= cls
982 || n
->u
.vbuiltin
->instance_context
== NULL
)
985 if (instance_context_return
)
987 instance
= (JSObjectInstanceCtx
*) n
->u
.vbuiltin
->instance_context
;
988 *instance_context_return
= instance
->instance_context
;
996 /* Type functions. */
999 js_type_make_string (JSInterpPtr interp
, JSType
*type
, unsigned char *data
,
1000 unsigned int length
)
1002 JSNode
*n
= (JSNode
*) type
;
1004 js_vm_make_string (interp
->vm
, n
, data
, length
);
1009 js_type_make_array (JSInterpPtr interp
, JSType
*type
, unsigned int length
)
1011 JSNode
*n
= (JSNode
*) type
;
1013 js_vm_make_array (interp
->vm
, n
, length
);
1018 js_set_var (JSInterpPtr interp
, char *name
, JSType
*value
)
1020 JSNode
*n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, name
)];
1021 JS_COPY (n
, (JSNode
*) value
);
1026 js_get_var (JSInterpPtr interp
, char *name
, JSType
*value
)
1028 JSNode
*n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, name
)];
1029 JS_COPY ((JSNode
*) value
, n
);
1034 js_get_options (JSInterpPtr interp
, JSInterpOptions
*options
)
1036 memcpy (options
, &interp
->options
, sizeof (*options
));
1041 js_set_options (JSInterpPtr interp
, JSInterpOptions
*options
)
1043 memcpy (&interp
->options
, options
, sizeof (*options
));
1045 /* User can change the security options, */
1047 if (interp
->options
.secure_builtin_file
)
1048 interp
->vm
->security
|= JS_VM_SECURE_FILE
;
1050 interp
->vm
->security
&= ~JS_VM_SECURE_FILE
;
1052 if (interp
->options
.secure_builtin_system
)
1053 interp
->vm
->security
|= JS_VM_SECURE_SYSTEM
;
1055 interp
->vm
->security
&= ~JS_VM_SECURE_SYSTEM
;
1057 /* and the event hook. */
1058 interp
->vm
->hook
= options
->hook
;
1059 interp
->vm
->hook_context
= options
->hook_context
;
1060 interp
->vm
->hook_operand_count_trigger
= options
->hook_operand_count_trigger
;
1065 js_create_global_method (JSInterpPtr interp
, char *name
,
1066 JSGlobalMethodProc proc
, void *context
,
1067 JSFreeProc context_free_proc
)
1069 JSNode
*n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, name
)];
1070 JSVirtualMachine
*vm
= interp
->vm
;
1073 /* Need one toplevel here. */
1075 JSErrorHandlerFrame handler
;
1077 /* We must create the toplevel ourself. */
1078 memset (&handler
, 0, sizeof (handler
));
1079 handler
.next
= vm
->error_handler
;
1080 vm
->error_handler
= &handler
;
1082 if (setjmp (vm
->error_handler
->error_jmp
))
1083 /* An error occurred. */
1087 JSBuiltinInfo
*info
;
1088 JSGlobalMethodContext
*ctx
;
1091 ctx
= js_calloc (vm
, 1, sizeof (*ctx
));
1094 ctx
->context
= context
;
1095 ctx
->free_proc
= context_free_proc
;
1096 ctx
->interp
= interp
;
1099 info
= js_vm_builtin_info_create (vm
);
1100 info
->global_method_proc
= js_global_method_stub
;
1101 info
->delete_proc
= js_global_method_delete
;
1103 /* Create the builtin. */
1104 js_vm_builtin_create (interp
->vm
, n
, info
, ctx
);
1107 /* Pop the error handler. */
1108 vm
->error_handler
= vm
->error_handler
->next
;
1116 js_define_module (JSInterpPtr interp
, JSModuleInitProc init_proc
)
1118 JSErrorHandlerFrame handler
;
1119 JSVirtualMachine
*vm
= interp
->vm
;
1122 /* Just call the init proc in a toplevel. */
1124 memset (&handler
, 0, sizeof (handler
));
1125 handler
.next
= vm
->error_handler
;
1126 vm
->error_handler
= &handler
;
1128 if (setjmp (vm
->error_handler
->error_jmp
))
1129 /* An error occurred. */
1132 /* Call the module init proc. */
1133 (*init_proc
) (interp
);
1135 /* Pop the error handler. */
1136 vm
->error_handler
= vm
->error_handler
->next
;
1148 js_eval_source (JSInterpPtr interp
, JSNode
*source
, char *compiler_function
)
1155 /* Let's compile the code. */
1157 /* Argument count. */
1158 argv
[i
].type
= JS_INTEGER
;
1159 argv
[i
].u
.vinteger
= 4;
1162 /* Source to compiler. */
1163 JS_COPY (&argv
[i
], source
);
1167 argv
[i
].type
= JS_INTEGER
;
1168 argv
[i
].u
.vinteger
= 0;
1170 if (interp
->options
.verbose
)
1171 argv
[i
].u
.vinteger
= JSC_FLAG_VERBOSE
;
1173 argv
[i
].u
.vinteger
|= JSC_FLAG_GENERATE_DEBUG_INFO
;
1175 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_PEEPHOLE
;
1176 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_JUMPS
;
1177 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_WITH_CLOBBER
;
1180 /* Assembler file. */
1181 argv
[i
].type
= JS_NULL
;
1184 /* Byte-code file. */
1185 argv
[i
].type
= JS_NULL
;
1188 /* Call the compiler entry point. */
1189 result
= js_vm_apply (interp
->vm
, compiler_function
, NULL
, i
, argv
);
1194 * The resulting byte-code file is now at vm->exec_result.
1196 * Note! The byte-code is a string allocated form the vm heap.
1197 * The garbage collector can free it when it wants since the result
1198 * isn't protected. However, we have no risk here because we
1199 * first convert the byte-code data block to our internal
1200 * JSByteCode block that shares no memory with the original data.
1203 assert (interp
->vm
->exec_result
.type
== JS_STRING
);
1205 bc
= js_bc_read_data (interp
->vm
->exec_result
.u
.vstring
->data
,
1206 interp
->vm
->exec_result
.u
.vstring
->len
);
1208 /* And finally, execute it. */
1209 result
= js_vm_execute (interp
->vm
, bc
);
1211 /* Free the byte-code. */
1219 js_compile_source (JSInterpPtr interp
, JSNode
*source
,
1220 char *compiler_function
, char *assembler_file
,
1221 char *byte_code_file
, JSNode
*bc_return
)
1227 /* Init arguments. */
1229 argv
[i
].type
= JS_INTEGER
;
1230 argv
[i
].u
.vinteger
= 4;
1233 /* Source to compiler. */
1234 JS_COPY (&argv
[1], source
);
1238 argv
[i
].type
= JS_INTEGER
;
1239 argv
[i
].u
.vinteger
= 0;
1241 if (interp
->options
.verbose
)
1242 argv
[i
].u
.vinteger
|= JSC_FLAG_VERBOSE
;
1243 if (interp
->options
.annotate_assembler
)
1244 argv
[i
].u
.vinteger
|= JSC_FLAG_ANNOTATE_ASSEMBLER
;
1245 if (interp
->options
.debug_info
)
1246 argv
[i
].u
.vinteger
|= JSC_FLAG_GENERATE_DEBUG_INFO
;
1247 if (interp
->options
.executable_bc_files
)
1248 argv
[i
].u
.vinteger
|= JSC_FLAG_GENERATE_EXECUTABLE_BC_FILES
;
1250 if (interp
->options
.warn_unused_argument
)
1251 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_UNUSED_ARGUMENT
;
1252 if (interp
->options
.warn_unused_variable
)
1253 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_UNUSED_VARIABLE
;
1254 if (interp
->options
.warn_shadow
)
1255 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_SHADOW
;
1256 if (interp
->options
.warn_with_clobber
)
1257 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_WITH_CLOBBER
;
1258 if (interp
->options
.warn_missing_semicolon
)
1259 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_MISSING_SEMICOLON
;
1260 if (interp
->options
.warn_strict_ecma
)
1261 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_STRICT_ECMA
;
1262 if (interp
->options
.warn_deprecated
)
1263 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_DEPRECATED
;
1265 if (interp
->options
.optimize_peephole
)
1266 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_PEEPHOLE
;
1267 if (interp
->options
.optimize_jumps_to_jumps
)
1268 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_JUMPS
;
1269 if (interp
->options
.optimize_bc_size
)
1270 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_BC_SIZE
;
1271 if (interp
->options
.optimize_heavy
)
1272 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_HEAVY
;
1276 /* Assembler file. */
1278 js_vm_make_static_string (interp
->vm
, &argv
[i
], assembler_file
,
1279 strlen (assembler_file
));
1281 argv
[i
].type
= JS_NULL
;
1284 /* Byte-code file. */
1286 js_vm_make_static_string (interp
->vm
, &argv
[i
], byte_code_file
,
1287 strlen (byte_code_file
));
1289 argv
[i
].type
= JS_NULL
;
1292 /* Call the compiler entry point. */
1293 result
= js_vm_apply (interp
->vm
, compiler_function
, NULL
, i
, argv
);
1298 /* User wanted to get the resulting byte-code data. Here it is. */
1299 JS_COPY (bc_return
, &interp
->vm
->exec_result
);
1310 eval_global_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1311 void *instance_context
, JSNode
*result_return
,
1314 JSInterpPtr interp
= instance_context
;
1316 if (args
->u
.vinteger
!= 1)
1318 sprintf (vm
->error
, "eval(): illegal amount of arguments");
1321 if (args
[1].type
!= JS_STRING
)
1323 /* Return it to the caller. */
1324 JS_COPY (result_return
, &args
[1]);
1329 * Ok, we'r ready to eval it. The source strings is our argument, so,
1330 * it is in the stack and therefore, protected for gc.
1332 if (!js_eval_source (interp
, &args
[1], "JSC$compile_string"))
1334 /* The evaluation failed. Throw it as an error to our caller. */
1338 /* Pass the return value to our caller. */
1339 JS_COPY (result_return
, &vm
->exec_result
);
1344 load_global_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1345 void *instance_context
,
1346 JSNode
*result_return
, JSNode
*args
)
1348 JSInterpPtr interp
= instance_context
;
1352 if (args
->u
.vinteger
== 0)
1354 sprintf (vm
->error
, "load(): no arguments given");
1358 for (i
= 1; i
<= args
->u
.vinteger
; i
++)
1362 if (args
[i
].type
!= JS_STRING
)
1364 sprintf (vm
->error
, "load(): illegal argument");
1368 cp
= js_string_to_c_string (vm
, &args
[i
]);
1369 result
= js_eval_file (interp
, cp
);
1376 result_return
->type
= JS_BOOLEAN
;
1377 result_return
->u
.vboolean
= 1;
1382 load_class_global_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1383 void *instance_context
,
1384 JSNode
*result_return
, JSNode
*args
)
1386 JSInterpPtr interp
= instance_context
;
1389 if (args
->u
.vinteger
== 0)
1391 sprintf (vm
->error
, "loadClass(): no arguments given");
1395 for (i
= 1; i
<= args
->u
.vinteger
; i
++)
1399 void (*func
) (JSInterpPtr interp
);
1403 if (args
[i
].type
!= JS_STRING
)
1405 sprintf (vm
->error
, "loadClass(): illegal argument");
1409 cp
= js_string_to_c_string (vm
, &args
[i
]);
1411 /* Extract the function name. */
1412 func_name
= strrchr (cp
, ':');
1413 if (func_name
== NULL
)
1415 func_name
= strrchr (cp
, '/');
1416 if (func_name
== NULL
)
1427 /* Try to open the library. */
1428 lib
= js_dl_open (cp
, buf
, sizeof (buf
));
1431 sprintf (vm
->error
, "loadClass(): couldn't open library `%s': %s",
1437 * Strip all suffixes from the library name: if the <func_name>
1438 * is extracted from it, this will convert the library name
1439 * `foo.so.x.y' to the canonical entry point name `foo'.
1441 cp2
= strchr (cp
, '.');
1445 func
= js_dl_sym (lib
, func_name
, buf
, sizeof (buf
));
1449 "loadClass(): couldn't find the init function `%s': %s",
1454 /* All done with this argument. */
1458 * And finally, call the library entry point. All possible errors
1459 * will throw us to the containing top-level.
1464 result_return
->type
= JS_UNDEFINED
;
1469 call_method_global_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1470 void *instance_context
,
1471 JSNode
*result_return
, JSNode
*args
)
1473 JSInterpPtr interp
= instance_context
;
1479 if (args
->u
.vinteger
!= 3)
1481 sprintf (vm
->error
, "callMethod(): illegal amount of arguments");
1484 if (args
[2].type
!= JS_STRING
)
1487 sprintf (vm
->error
, "callMethod(): illegal argument");
1490 if (args
[3].type
!= JS_ARRAY
)
1491 goto illegal_argument
;
1493 /* Create the argument array. */
1494 argv
= js_malloc (vm
, (args
[3].u
.varray
->length
+ 1) * sizeof (JSNode
));
1496 /* The argument count. */
1497 argv
[0].type
= JS_INTEGER
;
1498 argv
[0].u
.vinteger
= args
[3].u
.varray
->length
;
1500 for (i
= 0; i
< args
[3].u
.varray
->length
; i
++)
1501 JS_COPY (&argv
[i
+ 1], &args
[3].u
.varray
->data
[i
]);
1503 /* Method name to C string. */
1504 cp
= js_string_to_c_string (vm
, &args
[2]);
1507 result
= js_vm_call_method (vm
, &args
[1], cp
, args
[3].u
.varray
->length
+ 1,
1515 JS_COPY (result_return
, &vm
->exec_result
);
1517 /* The error message is already there. */
1523 js_core_globals (JSInterpPtr interp
)
1526 JSBuiltinInfo
*info
;
1527 JSVirtualMachine
*vm
= interp
->vm
;
1529 if (!interp
->options
.no_compiler
)
1531 /* Command `eval'. */
1533 info
= js_vm_builtin_info_create (vm
);
1534 info
->global_method_proc
= eval_global_method
;
1536 n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, "eval")];
1538 js_vm_builtin_create (interp
->vm
, n
, info
, interp
);
1541 /* Command `load'. */
1543 info
= js_vm_builtin_info_create (vm
);
1544 info
->global_method_proc
= load_global_method
;
1546 n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, "load")];
1547 js_vm_builtin_create (interp
->vm
, n
, info
, interp
);
1549 /* Command `loadClass'. */
1551 info
= js_vm_builtin_info_create (vm
);
1552 info
->global_method_proc
= load_class_global_method
;
1554 n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, "loadClass")];
1555 js_vm_builtin_create (interp
->vm
, n
, info
, interp
);
1557 /* Command `callMethod'. */
1559 info
= js_vm_builtin_info_create (vm
);
1560 info
->global_method_proc
= call_method_global_method
;
1562 n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, "callMethod")];
1563 js_vm_builtin_create (interp
->vm
, n
, info
, interp
);
1568 js_global_method_stub (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1569 void *instance_context
, JSNode
*result_return
,
1572 JSMethodResult result
;
1573 JSGlobalMethodContext
*ctx
= instance_context
;
1575 /* Set the default result. */
1576 result_return
->type
= JS_UNDEFINED
;
1578 /* Call the user supplied function. */
1579 result
= (*ctx
->proc
) (ctx
->context
, ctx
->interp
, args
->u
.vinteger
,
1580 (JSType
*) &args
[1], (JSType
*) result_return
,
1582 if (result
!= JS_OK
)
1583 js_vm_error (ctx
->interp
->vm
);
1588 js_global_method_delete (JSBuiltinInfo
*builtin_info
, void *instance_context
)
1590 JSGlobalMethodContext
*ctx
= instance_context
;
1595 (*ctx
->free_proc
) (ctx
->context
);
1602 /* I/O Stream to user I/O function. */
1605 iofunc_io (void *context
, unsigned char *buffer
, unsigned int todo
,
1608 JSUserIOFuncCtx
*ctx
= context
;
1613 moved
= (*ctx
->func
) (ctx
->context
, buffer
, todo
);
1615 ctx
->position
+= moved
;
1622 iofunc_seek (void *context
, long offset
, int whence
)
1629 iofunc_get_position (void *context
)
1631 JSUserIOFuncCtx
*ctx
= context
;
1633 return ctx
->position
;
1638 iofunc_get_length (void *context
)
1645 iofunc_close (void *context
)
1652 iostream_iofunc (JSIOFunc func
, void *context
, int readp
, int writep
)
1654 JSIOStream
*stream
= js_iostream_new ();
1655 JSUserIOFuncCtx
*ctx
;
1660 ctx
= js_malloc (NULL
, sizeof (*ctx
));
1663 (void) js_iostream_close (stream
);
1669 ctx
->context
= context
;
1673 stream
->read
= iofunc_io
;
1675 stream
->write
= iofunc_io
;
1677 stream
->seek
= iofunc_seek
;
1678 stream
->get_position
= iofunc_get_position
;
1679 stream
->get_length
= iofunc_get_length
;
1680 stream
->close
= iofunc_close
;
1681 stream
->context
= ctx
;