📄 js.c
字号:
(cls->num_methods + 1) * sizeof (JSMethodReg));
if (nmethods == NULL)
return 0;
cls->methods = nmethods;
/*
* The names are interned to symbols when the class is defined to the
* interpreter.
*/
cls->methods[cls->num_methods].name = js_strdup (NULL, name);
if (cls->methods[cls->num_methods].name == NULL)
return 0;
cls->methods[cls->num_methods].flags = flags;
cls->methods[cls->num_methods].method = method;
cls->num_methods++;
return 1;
}
int
js_class_define_property (JSClassPtr cls, char *name, unsigned int flags,
JSPropertyProc property)
{
JSPropertyReg *nprops;
nprops = js_realloc (NULL, cls->properties,
(cls->num_properties + 1) * sizeof (JSPropertyReg));
if (nprops == NULL)
return 0;
cls->properties = nprops;
cls->properties[cls->num_properties].name = js_strdup (NULL, name);
if (cls->properties[cls->num_properties].name == NULL)
return 0;
cls->properties[cls->num_properties].flags = flags;
cls->properties[cls->num_properties].property = property;
cls->num_properties++;
return 1;
}
/* The stub functions for JSClass built-in objects. */
/* Method proc. */
static int
cls_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
void *instance_context, JSSymbol method, JSNode *result_return,
JSNode *args)
{
JSClassPtr cls = builtin_info->obj_context;
JSObjectInstanceCtx *ictx = instance_context;
int i;
JSMethodResult result;
char msg[1024];
/* Let's see if we know the method. */
for (i = 0; i < cls->num_methods; i++)
if (cls->methods[i].sym == method)
{
/* Found it. */
/* Check flags. */
if ((cls->methods[i].flags & JS_CF_STATIC) == 0
&& instance_context == NULL)
/* An instance method called from the `main' class. */
break;
result = (*cls->methods[i].method) (cls,
(ictx
? ictx->instance_context
: NULL),
cls->interp, args[0].u.vinteger,
(JSType *) &args[1],
(JSType *) result_return,
msg);
if (result == JS_ERROR)
{
sprintf (vm->error, "%s.%s(): %s", cls->name,
cls->methods[i].name, msg);
js_vm_error (vm);
}
return JS_PROPERTY_FOUND;
}
return JS_PROPERTY_UNKNOWN;
}
/* Property proc. */
static int
cls_property (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
void *instance_context, JSSymbol property, int set, JSNode *node)
{
JSClassPtr cls = builtin_info->obj_context;
JSObjectInstanceCtx *ictx = instance_context;
JSMethodResult result;
char msg[1024];
int i;
/* Find the property. */
for (i = 0; i < cls->num_properties; i++)
if (cls->properties[i].sym == property)
{
/* Found it. */
/* Check flags. */
if ((cls->properties[i].flags & JS_CF_STATIC) == 0
&& instance_context == NULL)
break;
if ((cls->properties[i].flags & JS_CF_IMMUTABLE) && set)
{
sprintf (vm->error, "%s.%s: immutable property",
cls->name, cls->properties[i].name);
js_vm_error (vm);
}
result = (*cls->properties[i].property) (cls,
(ictx
? ictx->instance_context
: NULL),
cls->interp, set,
(JSType *) node, msg);
if (result == JS_ERROR)
{
sprintf (vm->error, "%s.%s: %s", cls->name,
cls->properties[i].name, msg);
js_vm_error (vm);
}
return JS_PROPERTY_FOUND;
}
if (!set)
node->type = JS_UNDEFINED;
return JS_PROPERTY_UNKNOWN;
}
/* New proc. */
static void
cls_new_proc (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info, JSNode *args,
JSNode *result_return)
{
JSClassPtr cls = builtin_info->obj_context;
JSMethodResult result;
char msg[1024];
void *instance_context;
JSFreeProc instance_context_destructor;
JSObjectInstanceCtx *ictx;
result = (*cls->constructor) (cls, cls->interp, args[0].u.vinteger,
(JSType *) &args[1], &instance_context,
&instance_context_destructor,
msg);
if (result == JS_ERROR)
{
sprintf (vm->error, "new %s(): %s", cls->name, msg);
js_vm_error (vm);
}
ictx = js_calloc (vm, 1, sizeof (*ictx));
ictx->instance_context = instance_context;
ictx->instance_context_destructor = instance_context_destructor;
js_vm_builtin_create (vm, result_return, builtin_info, ictx);
}
/* Delete proc. */
static void
cls_delete_proc (JSBuiltinInfo *builtin_info, void *instance_context)
{
JSObjectInstanceCtx *ictx = instance_context;
if (ictx)
{
if (ictx->instance_context_destructor)
(*ictx->instance_context_destructor) (ictx->instance_context);
js_free (ictx);
}
}
/*
* This is called to destroy the class handle, when there are no more
* references to it.
*/
static void
js_class_destructor (void *context)
{
JSClassPtr cls = context;
if (cls->no_auto_destroy)
return;
js_class_destroy (cls);
}
static void
intern_symbols (JSVirtualMachine *vm, JSClassPtr cls)
{
int i;
for (i = 0; i < cls->num_methods; i++)
cls->methods[i].sym = js_vm_intern (vm, cls->methods[i].name);
for (i = 0; i < cls->num_properties; i++)
cls->properties[i].sym = js_vm_intern (vm, cls->properties[i].name);
cls->interned = 1;
}
static JSBuiltinInfo *
one_builtin_info_please (JSVirtualMachine *vm, JSClassPtr cls)
{
JSBuiltinInfo *info;
info = js_vm_builtin_info_create (vm);
info->method_proc = cls_method;
info->property_proc = cls_property;
if (cls->constructor)
{
info->new_proc = cls_new_proc;
info->delete_proc = cls_delete_proc;
}
info->obj_context = cls;
info->obj_context_delete = js_class_destructor;
return info;
}
int
js_define_class (JSInterpPtr interp, JSClassPtr cls, char *name)
{
JSNode *n;
JSVirtualMachine *vm = interp->vm;
JSBuiltinInfo *info;
/* XXX We need a top-level here */
cls->name = js_strdup (vm, name);
cls->interp = interp;
if (!cls->interned)
/* Intern the symbols and properties. */
intern_symbols (interp->vm, cls);
/* Define it to the interpreter. */
info = one_builtin_info_please (vm, cls);
n = &vm->globals[js_vm_intern (vm, name)];
js_vm_builtin_create (vm, n, info, NULL);
return 1;
}
int
js_instantiate_class (JSInterpPtr interp, JSClassPtr cls, void *ictx,
JSFreeProc ictx_destructor, JSType *result_return)
{
JSObjectInstanceCtx *instance;
JSVirtualMachine *vm = interp->vm;
JSBuiltinInfo *info;
if (!cls->interned)
/* Intern the symbols and properties. */
intern_symbols (vm, cls);
/* Create an instance. */
instance = js_calloc (vm, 1, sizeof (*instance));
instance->instance_context = ictx;
instance->instance_context_destructor = ictx_destructor;
/* Create a fresh builtin info. */
info = one_builtin_info_please (vm, cls);
/* And create it. */
js_vm_builtin_create (vm, (JSNode *) result_return, info, instance);
return 1;
}
JSClassPtr
js_lookup_class (JSInterpPtr interp, char *name)
{
JSNode *n;
JSVirtualMachine *vm = interp->vm;
n = &vm->globals[js_vm_intern (vm, name)];
if (n->type != JS_BUILTIN)
return NULL;
if (n->u.vbuiltin->info->method_proc != cls_method)
/* This is a wrong built-in. */
return NULL;
return (JSClassPtr) n->u.vbuiltin->info->obj_context;
}
int
js_isa (JSInterpPtr interp, JSType *object, JSClassPtr cls,
void **instance_context_return)
{
JSNode *n = (JSNode *) object;
JSObjectInstanceCtx *instance;
if (n->type != JS_BUILTIN || n->u.vbuiltin->info->obj_context != cls
|| n->u.vbuiltin->instance_context == NULL)
return 0;
if (instance_context_return)
{
instance = (JSObjectInstanceCtx *) n->u.vbuiltin->instance_context;
*instance_context_return = instance->instance_context;
}
return 1;
}
/* Type functions. */
void
js_type_make_string (JSInterpPtr interp, JSType *type, unsigned char *data,
unsigned int length)
{
JSNode *n = (JSNode *) type;
js_vm_make_string (interp->vm, n, (char*)data, length);
}
void
js_type_make_array (JSInterpPtr interp, JSType *type, unsigned int length)
{
JSNode *n = (JSNode *) type;
js_vm_make_array (interp->vm, n, length);
}
void
js_set_var (JSInterpPtr interp, char *name, JSType *value)
{
JSNode *n = &interp->vm->globals[js_vm_intern (interp->vm, name)];
JS_COPY (n, (JSNode *) value);
}
void
js_get_var (JSInterpPtr interp, char *name, JSType *value)
{
JSNode *n = &interp->vm->globals[js_vm_intern (interp->vm, name)];
JS_COPY ((JSNode *) value, n);
}
void
js_get_options (JSInterpPtr interp, JSInterpOptions *options)
{
memcpy (options, &interp->options, sizeof (*options));
}
void
js_set_options (JSInterpPtr interp, JSInterpOptions *options)
{
memcpy (&interp->options, options, sizeof (*options));
/* User can change the security options, */
if (interp->options.secure_builtin_file)
interp->vm->security |= JS_VM_SECURE_FILE;
else
interp->vm->security &= ~JS_VM_SECURE_FILE;
if (interp->options.secure_builtin_system)
interp->vm->security |= JS_VM_SECURE_SYSTEM;
else
interp->vm->security &= ~JS_VM_SECURE_SYSTEM;
/* and the event hook. */
interp->vm->hook = options->hook;
interp->vm->hook_context = options->hook_context;
interp->vm->hook_operand_count_trigger = options->hook_operand_count_trigger;
}
int
js_create_global_method (JSInterpPtr interp, char *name,
JSGlobalMethodProc proc, void *context,
JSFreeProc context_free_proc)
{
JSNode *n = &interp->vm->globals[js_vm_intern (interp->vm, name)];
JSVirtualMachine *vm = interp->vm;
int result = 1;
/* Need one toplevel here. */
{
JSErrorHandlerFrame handler;
/* We must create the toplevel ourself. */
memset (&handler, 0, sizeof (handler));
handler.next = vm->error_handler;
vm->error_handler = &handler;
if (setjmp (vm->error_handler->error_jmp))
/* An error occurred. */
result = 0;
else
{
JSBuiltinInfo *info;
JSGlobalMethodContext *ctx;
/* Context. */
ctx = js_calloc (vm, 1, sizeof (*ctx));
ctx->proc = proc;
ctx->context = context;
ctx->free_proc = context_free_proc;
ctx->interp = interp;
/* Info. */
info = js_vm_builtin_info_create (vm);
info->global_method_proc = js_global_method_stub;
info->delete_proc = js_global_method_delete;
/* Create the builtin. */
js_vm_builtin_create (interp->vm, n, info, ctx);
}
/* Pop the error handler. */
vm->error_handler = vm->error_handler->next;
}
return result;
}
int
js_define_module (JSInterpPtr interp, JSModuleInitProc init_proc)
{
JSErrorHandlerFrame handler;
JSVirtualMachine *vm = interp->vm;
int result = 1;
/* Just call the init proc in a toplevel. */
memset (&handler, 0, sizeof (handler));
handler.next = vm->error_handler;
vm->error_handler = &handler;
if (setjmp (vm->error_handler->error_jmp))
/* An error occurred. */
result = 0;
else
/* Call the module init proc. */
(*init_proc) (interp);
/* Pop the error handler. */
vm->error_handler = vm->error_handler->next;
return result;
}
/*
* Static functions.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -