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/ksrc/js.c,v $
27 * $Id: js.c,v 1.2 2004/05/07 05:12:10 royce Exp $
33 #include "ddk/kefuncs.h"
36 * Types and definitions.
39 /* Context for js_global_method_stub. */
40 struct js_global_method_context_st
42 JSGlobalMethodProc proc
;
48 typedef struct js_global_method_context_st JSGlobalMethodContext
;
50 /* Context for user I/O function streams. */
51 struct js_user_io_func_ctx_st
58 typedef struct js_user_io_func_ctx_st JSUserIOFuncCtx
;
60 struct js_method_reg_st
68 typedef struct js_method_reg_st JSMethodReg
;
70 struct js_property_reg_st
75 JSPropertyProc property
;
78 typedef struct js_property_reg_st JSPropertyReg
;
80 /* The class handle. */
87 unsigned int no_auto_destroy
: 1;
88 unsigned int interned
: 1;
91 JSFreeProc class_context_destructor
;
93 JSConstructor constructor
;
95 unsigned int num_methods
;
98 unsigned int num_properties
;
99 JSPropertyReg
*properties
;
102 /* Object instance context. */
103 struct js_object_instance_ctx_st
105 void *instance_context
;
106 JSFreeProc instance_context_destructor
;
109 typedef struct js_object_instance_ctx_st JSObjectInstanceCtx
;
113 * Prototypes for static functions.
116 /* The module for JS' core global methods. */
117 static void js_core_globals (JSInterpPtr interp
);
120 * Helper function to evaluate source <source> with compiler function
121 * <compiler_function>.
123 static int js_eval_source (JSInterpPtr interp
, JSNode
*source
,
124 char *compiler_function
);
127 * Helper function to compile source <source> with compiler function
128 * <compiler_function>. If <assembler_file> is not NULL, the
129 * assembler listing of the compilation is saved to that file. If
130 * <byte_code_file> is not NULL, the byte_code data is saved to that
131 * file. If <bc_return> is not NULL, the resulting byte_code data is
132 * returned in it as a JavaScript string node.
134 static int js_compile_source (JSInterpPtr interp
, JSNode
*source
,
135 char *compiler_function
, char *assembler_file
,
136 char *byte_code_file
, JSNode
*bc_return
);
139 * The stub function for global methods, created with the
140 * js_create_global_method() API function.
142 static void js_global_method_stub (JSVirtualMachine
*vm
,
143 JSBuiltinInfo
*builtin_info
,
144 void *instance_context
,
145 JSNode
*result_return
,
149 * Destructor for the global methods, created with the
150 * js_create_global_method() API function.
152 static void js_global_method_delete (JSBuiltinInfo
*builtin_info
,
153 void *instance_context
);
155 static JSIOStream
*iostream_iofunc (JSIOFunc func
, void *context
,
156 int readp
, int writep
);
171 js_init_default_options (JSInterpOptions
*options
)
173 memset (options
, 0, sizeof (*options
));
175 options
->stack_size
= 2048;
176 options
->dispatch_method
= JS_VM_DISPATCH_JUMPS
;
178 options
->warn_undef
= 1;
180 options
->optimize_peephole
= 1;
181 options
->optimize_jumps_to_jumps
= 1;
183 options
->fd_count
= (unsigned long) -1;
188 js_create_interp (JSInterpOptions
*options
, PKJS kjs
)
190 JSInterpPtr interp
= NULL
;
192 JSInterpOptions default_options
;
193 JSIOStream
*s_stdin
= NULL
;
194 JSIOStream
*s_stdout
= NULL
;
195 JSIOStream
*s_stderr
= NULL
;
198 * Sanity check to assure that the js.h and jsint.h APIs share a
199 * same view to the world.
201 assert (sizeof (JSNode
) == sizeof (JSType
));
203 interp
= js_calloc (NULL
, 1, sizeof (*interp
));
209 js_init_default_options (&default_options
);
210 options
= &default_options
;
213 memcpy (&interp
->options
, options
, sizeof (*options
));
215 /* The default system streams. */
217 s_stdin
= iostream_iofunc (options
->s_stdin
, options
->s_context
, 1, 0);
218 s_stdout
= iostream_iofunc (options
->s_stdout
, options
->s_context
, 0, 1);
219 s_stderr
= iostream_iofunc (options
->s_stderr
, options
->s_context
, 0, 1);
221 /* Create virtual machine. */
222 interp
->vm
= js_vm_create (kjs
,
224 options
->dispatch_method
,
226 options
->stacktrace_on_error
,
227 s_stdin
, s_stdout
, s_stderr
);
228 if (interp
->vm
== NULL
)
231 /* Set some options. */
232 interp
->vm
->warn_undef
= options
->warn_undef
;
234 /* Set the security options. */
236 if (options
->secure_builtin_file
)
237 interp
->vm
->security
|= JS_VM_SECURE_FILE
;
238 if (options
->secure_builtin_system
)
239 interp
->vm
->security
|= JS_VM_SECURE_SYSTEM
;
241 /* Set the event hook. */
242 interp
->vm
->hook
= options
->hook
;
243 interp
->vm
->hook_context
= options
->hook_context
;
244 interp
->vm
->hook_operand_count_trigger
= options
->hook_operand_count_trigger
;
246 /* The file descriptor limit. */
247 interp
->vm
->fd_count
= options
->fd_count
;
249 if (!options
->no_compiler
)
253 /* Define compiler to the virtual machine. */
254 bc
= js_bc_read_data (js_compiler_bytecode
, js_compiler_bytecode_len
);
258 result
= js_vm_execute (interp
->vm
, bc
);
264 /* Initialize our extensions. */
265 if (!js_define_module (interp
, js_core_globals
))
274 js_destroy_interp (JSInterpPtr interp
)
276 js_vm_destroy (interp
->vm
);
282 js_error_message (JSInterpPtr interp
)
284 return interp
->vm
->error
;
289 js_result (JSInterpPtr interp
, JSType
*result_return
)
291 memcpy (result_return
, &interp
->vm
->exec_result
, sizeof (*result_return
));
296 js_eval (JSInterpPtr interp
, char *code
)
300 js_vm_make_static_string (interp
->vm
, &source
, code
, strlen (code
));
301 return js_eval_source (interp
, &source
, "JSC$compile_string");
306 js_eval_data (JSInterpPtr interp
, char *data
, unsigned int datalen
)
310 js_vm_make_static_string (interp
->vm
, &source
, data
, datalen
);
311 return js_eval_source (interp
, &source
, "JSC$compile_string");
315 js_eval_javascript_file (JSInterpPtr interp
, char *filename
)
319 js_vm_make_static_string (interp
->vm
, &source
, filename
, strlen (filename
));
320 return js_eval_source (interp
, &source
, "JSC$compile_file");
325 js_execute_byte_code_file (JSInterpPtr interp
, char *filename
)
332 js_apply (JSInterpPtr interp
, char *name
, unsigned int argc
, JSType
*argv
)
338 args
= js_malloc (NULL
, (argc
+ 1) * sizeof (JSNode
));
341 sprintf (interp
->vm
->error
, "VM: out of memory");
345 /* Set the argument count. */
346 args
[0].type
= JS_INTEGER
;
347 args
[0].u
.vinteger
= argc
;
349 /* Set the arguments. */
350 for (ui
= 0; ui
< argc
; ui
++)
351 JS_COPY (&args
[ui
+ 1], (JSNode
*) &argv
[ui
]);
354 result
= js_vm_apply (interp
->vm
, name
, NULL
, argc
+ 1, args
);
363 js_compile (JSInterpPtr interp
, char *input_file
, char *assembler_file
,
364 char *byte_code_file
)
368 js_vm_make_static_string (interp
->vm
, &source
, input_file
,
369 strlen (input_file
));
370 return js_compile_source (interp
, &source
, "JSC$compile_file",
371 assembler_file
, byte_code_file
, NULL
);
376 js_compile_to_byte_code (JSInterpPtr interp
, char *input_file
,
377 unsigned char **bc_return
,
378 unsigned int *bc_len_return
)
383 js_vm_make_static_string (interp
->vm
, &source
, input_file
,
384 strlen (input_file
));
385 result
= js_compile_source (interp
, &source
, "JSC$compile_file",
386 NULL
, NULL
, &source
);
390 /* Pass the data to the caller. */
391 *bc_return
= source
.u
.vstring
->data
;
392 *bc_len_return
= source
.u
.vstring
->len
;
399 js_compile_data_to_byte_code (JSInterpPtr interp
, char *data
,
400 unsigned int datalen
,
401 unsigned char **bc_return
,
402 unsigned int *bc_len_return
)
407 js_vm_make_static_string (interp
->vm
, &source
, data
, datalen
);
408 result
= js_compile_source (interp
, &source
, "JSC$compile_string",
409 NULL
, NULL
, &source
);
413 /* Pass the data to the caller. */
414 *bc_return
= source
.u
.vstring
->data
;
415 *bc_len_return
= source
.u
.vstring
->len
;
422 js_execute_byte_code (JSInterpPtr interp
, unsigned char *bc_data
,
423 unsigned int bc_data_len
)
428 bc
= js_bc_read_data (bc_data
, bc_data_len
);
430 /* Not a valid byte-code data. */
434 result
= js_vm_execute (interp
->vm
, bc
);
444 js_class_create (void *class_context
, JSFreeProc class_context_destructor
,
445 int no_auto_destroy
, JSConstructor constructor
)
449 cls
= js_calloc (NULL
, 1, sizeof (*cls
));
453 cls
->class_context
= class_context
;
454 cls
->class_context_destructor
= class_context_destructor
;
456 cls
->no_auto_destroy
= no_auto_destroy
;
457 cls
->constructor
= constructor
;
464 js_class_destroy (JSClassPtr cls
)
469 if (cls
->class_context_destructor
)
470 (*cls
->class_context_destructor
) (cls
->class_context
);
477 js_class_context (JSClassPtr cls
)
480 return cls
->class_context
;
487 js_class_define_method (JSClassPtr cls
, char *name
, unsigned int flags
,
490 JSMethodReg
*nmethods
;
492 nmethods
= js_realloc (NULL
, cls
->methods
,
493 (cls
->num_methods
+ 1) * sizeof (JSMethodReg
));
494 if (nmethods
== NULL
)
497 cls
->methods
= nmethods
;
500 * The names are interned to symbols when the class is defined to the
504 cls
->methods
[cls
->num_methods
].name
= js_strdup (NULL
, name
);
505 if (cls
->methods
[cls
->num_methods
].name
== NULL
)
508 cls
->methods
[cls
->num_methods
].flags
= flags
;
509 cls
->methods
[cls
->num_methods
].method
= method
;
518 js_class_define_property (JSClassPtr cls
, char *name
, unsigned int flags
,
519 JSPropertyProc property
)
521 JSPropertyReg
*nprops
;
523 nprops
= js_realloc (NULL
, cls
->properties
,
524 (cls
->num_properties
+ 1) * sizeof (JSPropertyReg
));
528 cls
->properties
= nprops
;
530 cls
->properties
[cls
->num_properties
].name
= js_strdup (NULL
, name
);
531 if (cls
->properties
[cls
->num_properties
].name
== NULL
)
534 cls
->properties
[cls
->num_properties
].flags
= flags
;
535 cls
->properties
[cls
->num_properties
].property
= property
;
537 cls
->num_properties
++;
543 /* The stub functions for JSClass built-in objects. */
547 cls_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
548 void *instance_context
, JSSymbol method
, JSNode
*result_return
,
551 JSClassPtr cls
= builtin_info
->obj_context
;
552 JSObjectInstanceCtx
*ictx
= instance_context
;
554 JSMethodResult result
;
557 /* Let's see if we know the method. */
558 for (i
= 0; i
< cls
->num_methods
; i
++)
559 if (cls
->methods
[i
].sym
== method
)
564 if ((cls
->methods
[i
].flags
& JS_CF_STATIC
) == 0
565 && instance_context
== NULL
)
566 /* An instance method called from the `main' class. */
569 result
= (*cls
->methods
[i
].method
) (cls
,
571 ? ictx
->instance_context
573 cls
->interp
, args
[0].u
.vinteger
,
575 (JSType
*) result_return
,
577 if (result
== JS_ERROR
)
579 sprintf (vm
->error
, "%s.%s(): %s", cls
->name
,
580 cls
->methods
[i
].name
, msg
);
584 return JS_PROPERTY_FOUND
;
587 return JS_PROPERTY_UNKNOWN
;
592 cls_property (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
593 void *instance_context
, JSSymbol property
, int set
, JSNode
*node
)
595 JSClassPtr cls
= builtin_info
->obj_context
;
596 JSObjectInstanceCtx
*ictx
= instance_context
;
597 JSMethodResult result
;
601 /* Find the property. */
602 for (i
= 0; i
< cls
->num_properties
; i
++)
603 if (cls
->properties
[i
].sym
== property
)
609 if ((cls
->properties
[i
].flags
& JS_CF_STATIC
) == 0
610 && instance_context
== NULL
)
613 if ((cls
->properties
[i
].flags
& JS_CF_IMMUTABLE
) && set
)
615 sprintf (vm
->error
, "%s.%s: immutable property",
616 cls
->name
, cls
->properties
[i
].name
);
620 result
= (*cls
->properties
[i
].property
) (cls
,
622 ? ictx
->instance_context
625 (JSType
*) node
, msg
);
626 if (result
== JS_ERROR
)
628 sprintf (vm
->error
, "%s.%s: %s", cls
->name
,
629 cls
->properties
[i
].name
, msg
);
633 return JS_PROPERTY_FOUND
;
637 node
->type
= JS_UNDEFINED
;
639 return JS_PROPERTY_UNKNOWN
;
644 cls_new_proc (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
, JSNode
*args
,
645 JSNode
*result_return
)
647 JSClassPtr cls
= builtin_info
->obj_context
;
648 JSMethodResult result
;
650 void *instance_context
;
651 JSFreeProc instance_context_destructor
;
652 JSObjectInstanceCtx
*ictx
;
654 result
= (*cls
->constructor
) (cls
, cls
->interp
, args
[0].u
.vinteger
,
655 (JSType
*) &args
[1], &instance_context
,
656 &instance_context_destructor
,
658 if (result
== JS_ERROR
)
660 sprintf (vm
->error
, "new %s(): %s", cls
->name
, msg
);
664 ictx
= js_calloc (vm
, 1, sizeof (*ictx
));
665 ictx
->instance_context
= instance_context
;
666 ictx
->instance_context_destructor
= instance_context_destructor
;
668 js_vm_builtin_create (vm
, result_return
, builtin_info
, ictx
);
674 cls_delete_proc (JSBuiltinInfo
*builtin_info
, void *instance_context
)
676 JSObjectInstanceCtx
*ictx
= instance_context
;
680 if (ictx
->instance_context_destructor
)
681 (*ictx
->instance_context_destructor
) (ictx
->instance_context
);
688 * This is called to destroy the class handle, when there are no more
692 js_class_destructor (void *context
)
694 JSClassPtr cls
= context
;
696 if (cls
->no_auto_destroy
)
699 js_class_destroy (cls
);
704 intern_symbols (JSVirtualMachine
*vm
, JSClassPtr cls
)
708 for (i
= 0; i
< cls
->num_methods
; i
++)
709 cls
->methods
[i
].sym
= js_vm_intern (vm
, cls
->methods
[i
].name
);
711 for (i
= 0; i
< cls
->num_properties
; i
++)
712 cls
->properties
[i
].sym
= js_vm_intern (vm
, cls
->properties
[i
].name
);
718 static JSBuiltinInfo
*
719 one_builtin_info_please (JSVirtualMachine
*vm
, JSClassPtr cls
)
723 info
= js_vm_builtin_info_create (vm
);
725 info
->method_proc
= cls_method
;
726 info
->property_proc
= cls_property
;
728 if (cls
->constructor
)
730 info
->new_proc
= cls_new_proc
;
731 info
->delete_proc
= cls_delete_proc
;
734 info
->obj_context
= cls
;
735 info
->obj_context_delete
= js_class_destructor
;
742 js_define_class (JSInterpPtr interp
, JSClassPtr cls
, char *name
)
745 JSVirtualMachine
*vm
= interp
->vm
;
748 /* XXX We need a top-level here */
750 cls
->name
= js_strdup (vm
, name
);
751 cls
->interp
= interp
;
754 /* Intern the symbols and properties. */
755 intern_symbols (interp
->vm
, cls
);
757 /* Define it to the interpreter. */
759 info
= one_builtin_info_please (vm
, cls
);
761 n
= &vm
->globals
[js_vm_intern (vm
, name
)];
762 js_vm_builtin_create (vm
, n
, info
, NULL
);
769 js_instantiate_class (JSInterpPtr interp
, JSClassPtr cls
, void *ictx
,
770 JSFreeProc ictx_destructor
, JSType
*result_return
)
772 JSObjectInstanceCtx
*instance
;
773 JSVirtualMachine
*vm
= interp
->vm
;
777 /* Intern the symbols and properties. */
778 intern_symbols (vm
, cls
);
780 /* Create an instance. */
781 instance
= js_calloc (vm
, 1, sizeof (*instance
));
782 instance
->instance_context
= ictx
;
783 instance
->instance_context_destructor
= ictx_destructor
;
785 /* Create a fresh builtin info. */
786 info
= one_builtin_info_please (vm
, cls
);
789 js_vm_builtin_create (vm
, (JSNode
*) result_return
, info
, instance
);
796 js_lookup_class (JSInterpPtr interp
, char *name
)
799 JSVirtualMachine
*vm
= interp
->vm
;
801 n
= &vm
->globals
[js_vm_intern (vm
, name
)];
802 if (n
->type
!= JS_BUILTIN
)
805 if (n
->u
.vbuiltin
->info
->method_proc
!= cls_method
)
806 /* This is a wrong built-in. */
809 return (JSClassPtr
) n
->u
.vbuiltin
->info
->obj_context
;
814 js_isa (JSInterpPtr interp
, JSType
*object
, JSClassPtr cls
,
815 void **instance_context_return
)
817 JSNode
*n
= (JSNode
*) object
;
818 JSObjectInstanceCtx
*instance
;
820 if (n
->type
!= JS_BUILTIN
|| n
->u
.vbuiltin
->info
->obj_context
!= cls
821 || n
->u
.vbuiltin
->instance_context
== NULL
)
824 if (instance_context_return
)
826 instance
= (JSObjectInstanceCtx
*) n
->u
.vbuiltin
->instance_context
;
827 *instance_context_return
= instance
->instance_context
;
835 /* Type functions. */
838 js_type_make_string (JSInterpPtr interp
, JSType
*type
, unsigned char *data
,
841 JSNode
*n
= (JSNode
*) type
;
843 js_vm_make_string (interp
->vm
, n
, data
, length
);
848 js_type_make_array (JSInterpPtr interp
, JSType
*type
, unsigned int length
)
850 JSNode
*n
= (JSNode
*) type
;
852 js_vm_make_array (interp
->vm
, n
, length
);
857 js_set_var (JSInterpPtr interp
, char *name
, JSType
*value
)
859 JSNode
*n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, name
)];
860 JS_COPY (n
, (JSNode
*) value
);
865 js_get_var (JSInterpPtr interp
, char *name
, JSType
*value
)
867 JSNode
*n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, name
)];
868 JS_COPY ((JSNode
*) value
, n
);
873 js_get_options (JSInterpPtr interp
, JSInterpOptions
*options
)
875 memcpy (options
, &interp
->options
, sizeof (*options
));
880 js_set_options (JSInterpPtr interp
, JSInterpOptions
*options
)
882 memcpy (&interp
->options
, options
, sizeof (*options
));
884 /* User can change the security options, */
886 if (interp
->options
.secure_builtin_file
)
887 interp
->vm
->security
|= JS_VM_SECURE_FILE
;
889 interp
->vm
->security
&= ~JS_VM_SECURE_FILE
;
891 if (interp
->options
.secure_builtin_system
)
892 interp
->vm
->security
|= JS_VM_SECURE_SYSTEM
;
894 interp
->vm
->security
&= ~JS_VM_SECURE_SYSTEM
;
896 /* and the event hook. */
897 interp
->vm
->hook
= options
->hook
;
898 interp
->vm
->hook_context
= options
->hook_context
;
899 interp
->vm
->hook_operand_count_trigger
= options
->hook_operand_count_trigger
;
904 js_create_global_method (JSInterpPtr interp
, char *name
,
905 JSGlobalMethodProc proc
, void *context
,
906 JSFreeProc context_free_proc
)
908 JSNode
*n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, name
)];
909 JSVirtualMachine
*vm
= interp
->vm
;
912 /* Need one toplevel here. */
914 JSErrorHandlerFrame handler
;
916 /* We must create the toplevel ourself. */
917 memset (&handler
, 0, sizeof (handler
));
918 handler
.next
= vm
->error_handler
;
919 vm
->error_handler
= &handler
;
921 if (setjmp (vm
->error_handler
->error_jmp
))
922 /* An error occurred. */
927 JSGlobalMethodContext
*ctx
;
930 ctx
= js_calloc (vm
, 1, sizeof (*ctx
));
933 ctx
->context
= context
;
934 ctx
->free_proc
= context_free_proc
;
935 ctx
->interp
= interp
;
938 info
= js_vm_builtin_info_create (vm
);
939 info
->global_method_proc
= js_global_method_stub
;
940 info
->delete_proc
= js_global_method_delete
;
942 /* Create the builtin. */
943 js_vm_builtin_create (interp
->vm
, n
, info
, ctx
);
946 /* Pop the error handler. */
947 vm
->error_handler
= vm
->error_handler
->next
;
955 js_define_module (JSInterpPtr interp
, JSModuleInitProc init_proc
)
957 JSErrorHandlerFrame handler
;
958 JSVirtualMachine
*vm
= interp
->vm
;
961 /* Just call the init proc in a toplevel. */
963 memset (&handler
, 0, sizeof (handler
));
964 handler
.next
= vm
->error_handler
;
965 vm
->error_handler
= &handler
;
967 if (setjmp (vm
->error_handler
->error_jmp
))
968 /* An error occurred. */
971 /* Call the module init proc. */
972 (*init_proc
) (interp
);
974 /* Pop the error handler. */
975 vm
->error_handler
= vm
->error_handler
->next
;
987 js_eval_source (JSInterpPtr interp
, JSNode
*source
, char *compiler_function
)
994 /* Let's compile the code. */
996 /* Argument count. */
997 argv
[i
].type
= JS_INTEGER
;
998 argv
[i
].u
.vinteger
= 4;
1001 /* Source to compiler. */
1002 JS_COPY (&argv
[i
], source
);
1006 argv
[i
].type
= JS_INTEGER
;
1007 argv
[i
].u
.vinteger
= 0;
1009 if (interp
->options
.verbose
)
1010 argv
[i
].u
.vinteger
= JSC_FLAG_VERBOSE
;
1012 argv
[i
].u
.vinteger
|= JSC_FLAG_GENERATE_DEBUG_INFO
;
1014 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_PEEPHOLE
;
1015 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_JUMPS
;
1016 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_WITH_CLOBBER
;
1019 /* Assembler file. */
1020 argv
[i
].type
= JS_NULL
;
1023 /* Byte-code file. */
1024 argv
[i
].type
= JS_NULL
;
1027 /* Call the compiler entry point. */
1028 result
= js_vm_apply (interp
->vm
, compiler_function
, NULL
, i
, argv
);
1033 * The resulting byte-code file is now at vm->exec_result.
1035 * Note! The byte-code is a string allocated form the vm heap.
1036 * The garbage collector can free it when it wants since the result
1037 * isn't protected. However, we have no risk here because we
1038 * first convert the byte-code data block to our internal
1039 * JSByteCode block that shares no memory with the original data.
1042 assert (interp
->vm
->exec_result
.type
== JS_STRING
);
1044 bc
= js_bc_read_data (interp
->vm
->exec_result
.u
.vstring
->data
,
1045 interp
->vm
->exec_result
.u
.vstring
->len
);
1047 /* And finally, execute it. */
1048 result
= js_vm_execute (interp
->vm
, bc
);
1050 /* Free the byte-code. */
1058 js_compile_source (JSInterpPtr interp
, JSNode
*source
,
1059 char *compiler_function
, char *assembler_file
,
1060 char *byte_code_file
, JSNode
*bc_return
)
1066 /* Init arguments. */
1068 argv
[i
].type
= JS_INTEGER
;
1069 argv
[i
].u
.vinteger
= 4;
1072 /* Source to compiler. */
1073 JS_COPY (&argv
[1], source
);
1077 argv
[i
].type
= JS_INTEGER
;
1078 argv
[i
].u
.vinteger
= 0;
1080 if (interp
->options
.verbose
)
1081 argv
[i
].u
.vinteger
|= JSC_FLAG_VERBOSE
;
1082 if (interp
->options
.annotate_assembler
)
1083 argv
[i
].u
.vinteger
|= JSC_FLAG_ANNOTATE_ASSEMBLER
;
1084 if (interp
->options
.debug_info
)
1085 argv
[i
].u
.vinteger
|= JSC_FLAG_GENERATE_DEBUG_INFO
;
1086 if (interp
->options
.executable_bc_files
)
1087 argv
[i
].u
.vinteger
|= JSC_FLAG_GENERATE_EXECUTABLE_BC_FILES
;
1089 if (interp
->options
.warn_unused_argument
)
1090 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_UNUSED_ARGUMENT
;
1091 if (interp
->options
.warn_unused_variable
)
1092 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_UNUSED_VARIABLE
;
1093 if (interp
->options
.warn_shadow
)
1094 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_SHADOW
;
1095 if (interp
->options
.warn_with_clobber
)
1096 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_WITH_CLOBBER
;
1097 if (interp
->options
.warn_missing_semicolon
)
1098 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_MISSING_SEMICOLON
;
1099 if (interp
->options
.warn_strict_ecma
)
1100 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_STRICT_ECMA
;
1101 if (interp
->options
.warn_deprecated
)
1102 argv
[i
].u
.vinteger
|= JSC_FLAG_WARN_DEPRECATED
;
1104 if (interp
->options
.optimize_peephole
)
1105 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_PEEPHOLE
;
1106 if (interp
->options
.optimize_jumps_to_jumps
)
1107 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_JUMPS
;
1108 if (interp
->options
.optimize_bc_size
)
1109 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_BC_SIZE
;
1110 if (interp
->options
.optimize_heavy
)
1111 argv
[i
].u
.vinteger
|= JSC_FLAG_OPTIMIZE_HEAVY
;
1115 /* Assembler file. */
1117 js_vm_make_static_string (interp
->vm
, &argv
[i
], assembler_file
,
1118 strlen (assembler_file
));
1120 argv
[i
].type
= JS_NULL
;
1123 /* Byte-code file. */
1125 js_vm_make_static_string (interp
->vm
, &argv
[i
], byte_code_file
,
1126 strlen (byte_code_file
));
1128 argv
[i
].type
= JS_NULL
;
1131 /* Call the compiler entry point. */
1132 result
= js_vm_apply (interp
->vm
, compiler_function
, NULL
, i
, argv
);
1137 /* User wanted to get the resulting byte-code data. Here it is. */
1138 JS_COPY (bc_return
, &interp
->vm
->exec_result
);
1149 eval_global_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1150 void *instance_context
, JSNode
*result_return
,
1153 JSInterpPtr interp
= instance_context
;
1155 if (args
->u
.vinteger
!= 1)
1157 sprintf (vm
->error
, "eval(): illegal amount of arguments");
1160 if (args
[1].type
!= JS_STRING
)
1162 /* Return it to the caller. */
1163 JS_COPY (result_return
, &args
[1]);
1168 * Ok, we'r ready to eval it. The source strings is our argument, so,
1169 * it is in the stack and therefore, protected for gc.
1171 if (!js_eval_source (interp
, &args
[1], "JSC$compile_string"))
1173 /* The evaluation failed. Throw it as an error to our caller. */
1177 /* Pass the return value to our caller. */
1178 JS_COPY (result_return
, &vm
->exec_result
);
1182 load_class_global_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1183 void *instance_context
,
1184 JSNode
*result_return
, JSNode
*args
)
1186 JSInterpPtr interp
= instance_context
;
1189 if (args
->u
.vinteger
== 0)
1191 sprintf (vm
->error
, "loadClass(): no arguments given");
1195 for (i
= 1; i
<= args
->u
.vinteger
; i
++)
1199 void (*func
) (JSInterpPtr interp
);
1203 if (args
[i
].type
!= JS_STRING
)
1205 sprintf (vm
->error
, "loadClass(): illegal argument");
1209 cp
= js_string_to_c_string (vm
, &args
[i
]);
1211 /* Extract the function name. */
1212 func_name
= strrchr (cp
, ':');
1213 if (func_name
== NULL
)
1215 func_name
= strrchr (cp
, '/');
1216 if (func_name
== NULL
)
1227 /* Try to open the library. */
1228 lib
= js_dl_open (cp
, buf
, sizeof (buf
));
1231 sprintf (vm
->error
, "loadClass(): couldn't open library `%s': %s",
1237 * Strip all suffixes from the library name: if the <func_name>
1238 * is extracted from it, this will convert the library name
1239 * `foo.so.x.y' to the canonical entry point name `foo'.
1241 cp2
= strchr (cp
, '.');
1245 func
= js_dl_sym (lib
, func_name
, buf
, sizeof (buf
));
1249 "loadClass(): couldn't find the init function `%s': %s",
1254 /* All done with this argument. */
1258 * And finally, call the library entry point. All possible errors
1259 * will throw us to the containing top-level.
1264 result_return
->type
= JS_UNDEFINED
;
1269 call_method_global_method (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1270 void *instance_context
,
1271 JSNode
*result_return
, JSNode
*args
)
1273 /* JSInterpPtr interp = instance_context; */
1279 if (args
->u
.vinteger
!= 3)
1281 sprintf (vm
->error
, "callMethod(): illegal amount of arguments");
1284 if (args
[2].type
!= JS_STRING
)
1287 sprintf (vm
->error
, "callMethod(): illegal argument");
1290 if (args
[3].type
!= JS_ARRAY
)
1291 goto illegal_argument
;
1293 /* Create the argument array. */
1294 argv
= js_malloc (vm
, (args
[3].u
.varray
->length
+ 1) * sizeof (JSNode
));
1296 /* The argument count. */
1297 argv
[0].type
= JS_INTEGER
;
1298 argv
[0].u
.vinteger
= args
[3].u
.varray
->length
;
1300 for (i
= 0; i
< args
[3].u
.varray
->length
; i
++)
1301 JS_COPY (&argv
[i
+ 1], &args
[3].u
.varray
->data
[i
]);
1303 /* Method name to C string. */
1304 cp
= js_string_to_c_string (vm
, &args
[2]);
1307 result
= js_vm_call_method (vm
, &args
[1], cp
, args
[3].u
.varray
->length
+ 1,
1315 JS_COPY (result_return
, &vm
->exec_result
);
1317 /* The error message is already there. */
1323 js_core_globals (JSInterpPtr interp
)
1326 JSBuiltinInfo
*info
;
1327 JSVirtualMachine
*vm
= interp
->vm
;
1329 if (!interp
->options
.no_compiler
)
1331 /* Command `eval'. */
1333 info
= js_vm_builtin_info_create (vm
);
1334 info
->global_method_proc
= eval_global_method
;
1336 n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, "eval")];
1338 js_vm_builtin_create (interp
->vm
, n
, info
, interp
);
1341 /* Command `loadClass'. */
1343 info
= js_vm_builtin_info_create (vm
);
1344 info
->global_method_proc
= load_class_global_method
;
1346 n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, "loadClass")];
1347 js_vm_builtin_create (interp
->vm
, n
, info
, interp
);
1349 /* Command `callMethod'. */
1351 info
= js_vm_builtin_info_create (vm
);
1352 info
->global_method_proc
= call_method_global_method
;
1354 n
= &interp
->vm
->globals
[js_vm_intern (interp
->vm
, "callMethod")];
1355 js_vm_builtin_create (interp
->vm
, n
, info
, interp
);
1360 js_global_method_stub (JSVirtualMachine
*vm
, JSBuiltinInfo
*builtin_info
,
1361 void *instance_context
, JSNode
*result_return
,
1364 JSMethodResult result
;
1365 JSGlobalMethodContext
*ctx
= instance_context
;
1367 /* Set the default result. */
1368 result_return
->type
= JS_UNDEFINED
;
1370 /* Call the user supplied function. */
1371 result
= (*ctx
->proc
) (ctx
->context
, ctx
->interp
, args
->u
.vinteger
,
1372 (JSType
*) &args
[1], (JSType
*) result_return
,
1374 if (result
!= JS_OK
)
1375 js_vm_error (ctx
->interp
->vm
);
1380 js_global_method_delete (JSBuiltinInfo
*builtin_info
, void *instance_context
)
1382 JSGlobalMethodContext
*ctx
= instance_context
;
1387 (*ctx
->free_proc
) (ctx
->context
);
1394 /* I/O Stream to user I/O function. */
1397 iofunc_io (void *context
, unsigned char *buffer
, unsigned int todo
,
1400 JSUserIOFuncCtx
*ctx
= context
;
1405 moved
= (*ctx
->func
) (ctx
->context
, buffer
, todo
);
1407 ctx
->position
+= moved
;
1414 iofunc_seek (void *context
, long offset
, int whence
)
1421 iofunc_get_position (void *context
)
1423 JSUserIOFuncCtx
*ctx
= context
;
1425 return ctx
->position
;
1430 iofunc_get_length (void *context
)
1437 iofunc_close (void *context
)
1443 iostream_iofunc (JSIOFunc func
, void *context
, int readp
, int writep
)
1445 JSIOStream
*stream
= js_iostream_new ();
1446 JSUserIOFuncCtx
*ctx
;
1448 ctx
= js_malloc (NULL
, sizeof (*ctx
));
1451 (void) js_iostream_close (stream
);
1457 ctx
->context
= context
;
1461 stream
->read
= iofunc_io
;
1463 stream
->write
= iofunc_io
;
1465 stream
->seek
= iofunc_seek
;
1466 stream
->get_position
= iofunc_get_position
;
1467 stream
->get_length
= iofunc_get_length
;
1468 stream
->close
= iofunc_close
;
1469 stream
->context
= ctx
;