Exemple #1
0
static int
sort_js_cmp_func (const void *aptr, const void *bptr, void *context)
{
  ArraySortCtx *ctx = context;
  const JSNode *a = aptr;
  const JSNode *b = bptr;

  /*
   * Finalize the argument array.  The argumnet count has already been set.
   * when the context were initialized.
   */
  JS_COPY (&ctx->argv[1], a);
  JS_COPY (&ctx->argv[2], b);

  /* Call the function. */
  if (!js_vm_apply (ctx->vm, NULL, ctx->func, 3, ctx->argv))
    /* Raise an error. */
    js_vm_error (ctx->vm);

  /* Fetch the return value. */
  if (ctx->vm->exec_result.type != JS_INTEGER)
    {
      sprintf (ctx->vm->error,
	       "Array.sort(): comparison function didn't return integer");
      js_vm_error (ctx->vm);
    }

  return ctx->vm->exec_result.u.vinteger;
}
Exemple #2
0
void
js_vm_object_load_array (JSVirtualMachine *vm, JSObject *obj, JSNode *sel,
			 JSNode *value_return)
{
  if (sel->type == JS_INTEGER)
    {
      if (sel->u.vinteger < 0 || sel->u.vinteger >= obj->num_props)
	value_return->type = JS_UNDEFINED;
      else
	JS_COPY (value_return, &obj->props[sel->u.vinteger].value);
    }
  else if (sel->type == JS_STRING)
    {
      int pos;

      if (obj->hash == NULL)
	hash_create (vm, obj);

      pos = hash_lookup (obj, (char *) sel->u.vstring->data,
			 sel->u.vstring->len);
      if (pos < 0)
	value_return->type = JS_UNDEFINED;
      else
	JS_COPY (value_return, &obj->props[pos].value);
    }
  else
    {
      sprintf (vm->error, "load_property: illegal array index");
      js_vm_error (vm);
    }
}
Exemple #3
0
static void
eval_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
		    void *instance_context, JSNode *result_return,
		    JSNode *args)
{
  JSInterpPtr interp = instance_context;

  if (args->u.vinteger != 1)
    {
      sprintf (vm->error, "eval: illegal amount of arguments");
      js_vm_error (vm);
    }
  if (args[1].type != JS_STRING)
    {
      sprintf (vm->error, "eval: illegal argument");
      js_vm_error (vm);
    }

  /*
   * Ok, we'r ready to eval it.  The source strings is our argument, so,
   * it is in the stack and therefore, protected for gc.
   */
  if (!js_eval_source (interp, &args[1], "JSC$compile_string"))
    {
      /* The evaluation failed. */
      fprintf (stderr, "eval: evaluation failed: %s\n", vm->error);
      result_return->type = JS_UNDEFINED;
    }
  else
    /* Pass the return value to our caller. */
    JS_COPY (result_return, &vm->exec_result);
}
Exemple #4
0
int
js_vm_object_load_property (JSVirtualMachine *vm, JSObject *obj,
			    JSSymbol prop, JSNode *value_return)
{
  unsigned int ui;
  JSSymbol link_sym = vm->syms.s___proto__;
  JSObject *link_obj = NULL;

follow_link:

  /* Check if we know this property. */
  for (ui = 0; ui < obj->num_props; ui++)
    if (obj->props[ui].name == prop)
      {
	JS_COPY (value_return, &obj->props[ui].value);
	return JS_PROPERTY_FOUND;
      }
    else if (obj->props[ui].name == link_sym
	     && obj->props[ui].value.type == JS_OBJECT)
      link_obj = obj->props[ui].value.u.vobject;

  /* Undefined so far. */
  if (link_obj)
    {
      /* Follow the link. */
      obj = link_obj;

      link_obj = NULL;
      goto follow_link;
    }

  /* Undefined.  Make it undef. */
  value_return->type = JS_UNDEFINED;
  return JS_PROPERTY_UNKNOWN;
}
Exemple #5
0
void
js_vm_object_store_property (JSVirtualMachine *vm, JSObject *obj,
			     JSSymbol prop, JSNode *val)
{
  unsigned int ui;
  JSSymbol free_slot = JS_SYMBOL_NULL;

  /* Check if we already know this property. */
  for (ui = 0; ui < obj->num_props; ui++)
    if (obj->props[ui].name == prop)
      {
	JS_COPY (&obj->props[ui].value, val);
	return;
      }
    else if (obj->props[ui].name == JS_SYMBOL_NULL)
      free_slot = ui;

  /* Must create a new property. */

  if (free_slot == JS_SYMBOL_NULL)
    {
      /* Expand our array of properties. */
      obj->props = js_vm_realloc (vm, obj->props,
				  (obj->num_props + 1) * sizeof (JSProperty));
      free_slot = obj->num_props++;
    }

  obj->props[free_slot].name = prop;
  obj->props[free_slot].attributes = 0;
  JS_COPY (&obj->props[free_slot].value, val);

  /* Insert it to the hash (if the hash has been created). */
  if (obj->hash)
    {
      const char *name;

      name = js_vm_symname (vm, prop);
      hash_insert (vm, obj, name, strlen (name), free_slot);
    }
}
Exemple #6
0
/* New proc. */
static void
new_proc (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info, JSNode *args,
	  JSNode *result_return)
{
  int i;

  if (args->u.vinteger == 1 && args[1].type == JS_INTEGER)
    {
      /* Create a fixed length array. */
      js_vm_make_array (vm, result_return, args[1].u.vinteger);
    }
  else
    {
      js_vm_make_array (vm, result_return, args->u.vinteger);
      for (i = 0; i < args->u.vinteger; i++)
	JS_COPY (&result_return->u.varray->data[i], &args[i + 1]);
    }
}
Exemple #7
0
static void
execute_code (JSVirtualMachine *vm, JSNode *object, Function *f,
              unsigned int argc, JSNode *argv)
{
  JSNode *sp;
  JSNode *fp;
  JSNode *function;
  JSNode builtin_result;
  unsigned char *pc;
  JSInt32 i, j;
  JSInt8 i8;
  char buf[512];

  /* Create the initial stack frame by hand. */
  sp = vm->sp;

  /* Protect the function from gc. */
  JS_SP0->type = JS_FUNC;
  JS_SP0->u.vfunction = js_vm_make_function (vm, f);
  JS_PUSH ();

  /* Push arguments to the stack. */
  i = argc;
  for (i--; i >= 0; i--)
    {
      JS_COPY (JS_SP0, &argv[i]);
      JS_PUSH ();
    }

  /* This pointer. */
  if (object)
    JS_COPY (JS_SP0, object);
  else
    JS_SP0->type = JS_NULL;
  JS_PUSH ();

  /* Init fp and pc so our SUBROUTINE_CALL will work. */
  fp = NULL;
  pc = NULL;

  JS_SUBROUTINE_CALL (f);

  /* Ok, now we are ready to run. */

  while (1)
    {
      switch (*pc++)
        {
          /* include eswt0.h */
#include "eswt0.h"
          /* end include eswt0.h */

        default:
          sprintf_P (buf, vmswt0_string_5, *(pc - 1), JS_HOST_LINE_BREAK);
          //js_iostream_write (vm->s_stderr, buf, strlen (buf));
          //js_iostream_flush (vm->s_stderr);

          abort ();
          break;
        }
    }

 done:

  /* All done. */

  JS_COPY (&vm->exec_result, JS_SP1);
}
Exemple #8
0
/*
 * Static functions.
 */
static int
js_eval_source (JSInterpPtr interp, JSNode *source, char *compiler_function)
{
  JSNode argv[5];
  int i = 0;
  int result;
  JSByteCode *bc;

  /* Let's compile the code. */

  /* Argument count. */
  argv[i].type = JS_INTEGER;
  argv[i].u.vinteger = 4;
  i++;

  /* Source to compiler. */
  JS_COPY (&argv[i], source);
  i++;

  /* Flags. */
  argv[i].type = JS_INTEGER;
  argv[i].u.vinteger = 0;

  if (interp->options.verbose)
    argv[i].u.vinteger = JSC_FLAG_VERBOSE;

  argv[i].u.vinteger |= JSC_FLAG_GENERATE_DEBUG_INFO;

  argv[i].u.vinteger |= JSC_FLAG_OPTIMIZE_PEEPHOLE;
  argv[i].u.vinteger |= JSC_FLAG_OPTIMIZE_JUMPS;
  argv[i].u.vinteger |= JSC_FLAG_WARN_MASK;
  i++;

  /* Assembler file. */
  argv[i].type = JS_NULL;
  i++;

  /* Byte-code file. */
  argv[i].type = JS_NULL;
  i++;

  /* Call the compiler entry point. */
  result = js_vm_apply (interp->vm, compiler_function, NULL, i, argv);
  if (result == 0)
    return 0;

  /*
   * The resulting byte-code file is now at vm->exec_result.
   *
   * Note!  The byte-code is a string allocated form the vm heap.
   * The garbage collector can free it when it wants since the result
   * isn't protected.  However, we have no risk here because we
   * first convert the byte-code data block to our internal
   * JSByteCode block that shares no memory with the original data.
   */

  assert (interp->vm->exec_result.type == JS_STRING);

  bc = js_bc_read_data (interp->vm->exec_result.u.vstring->data,
			interp->vm->exec_result.u.vstring->len);

  /* And finally, execute it. */
  result = js_vm_execute (interp->vm, bc);

  /* Free the byte-code. */
  js_bc_free (bc);

  return result;
}
Exemple #9
0
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);
}
Exemple #10
0
static void
execute_code (JSVirtualMachine *vm, Function *f, unsigned int argc,
	      JSNode *argv)
{
  JSNode *sp;
  JSNode *fp;
  JSNode *function;
  JSNode builtin_result;
  Compiled *pc;
  JSInt32 i, j;
  JSInt8 i8;

  /* Create the initial stack frame by hand. */
  sp = vm->sp;

  /* Protect the function from gc. */
  JS_SP0->type = JS_FUNC;
  JS_SP0->u.vfunction = js_vm_make_function (vm, f);
  JS_PUSH ();

  /* Push arguments to the stack. */
  i = argc;
  for (i--; i >= 0; i--)
    {
      JS_COPY (JS_SP0, &argv[i]);
      JS_PUSH ();
    }

  /* Empty this pointer. */
  JS_SP0->type = JS_NULL;
  JS_PUSH ();

  /* Init fp and pc so our SUBROUTINE_CALL will work. */
  fp = NULL;
  pc = NULL;

  JS_SUBROUTINE_CALL (f);

  /* Ok, now we are ready to run. */

  while (1)
    {
      switch ((pc++)->u.op)
	{
	  /* include eswitch.h */
#include "eswitch.h"
	  /* end include eswitch.h */

	default:
	  fprintf (stderr, "execute_code: unknown opcode %d\n",
		   (pc - 1)->u.op);
	  exit (1);
	  break;
	}
    }

 done:

  /* All done. */
  JS_COPY (&vm->exec_result, JS_SP1);
}
Exemple #11
0
/* Method proc. */
static int
method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
	void *instance_context, JSSymbol method, JSNode *result_return,
	JSNode *args)
{
  ArrayCtx *ctx = builtin_info->obj_context;
  JSNode *n = instance_context;
  int i;

  /* Set the default result type. */
  result_return->type = JS_UNDEFINED;

  if (method == ctx->s_concat)
    {
      if (args->u.vinteger != 1)
	goto argument_error;
      if (args[1].type != JS_ARRAY)
	goto argument_type_error;

      js_vm_make_array (vm, result_return,
			n->u.varray->length + args[1].u.varray->length);

      memcpy (result_return->u.varray->data, n->u.varray->data,
	      n->u.varray->length * sizeof (JSNode));

      memcpy (&result_return->u.varray->data[n->u.varray->length],
	      args[1].u.varray->data,
	      args[1].u.varray->length * sizeof (JSNode));
    }
  /* ********************************************************************** */
  else if (method == ctx->s_join || method == vm->syms.s_toString)
    {
      char *glue = NULL;

      if (method == vm->syms.s_toString)
	{
	  if (args->u.vinteger != 0)
	    goto argument_error;
	}
      else
	{
	  if (args->u.vinteger == 0)
	    ;
	  else if (args->u.vinteger == 1)
	    {
	      JSNode glue_result;

	      js_vm_to_string (vm, &args[1], &glue_result);
	      glue = js_string_to_c_string (vm, &glue_result);
	    }
	  else
	    goto argument_error;
	}

      /* Ok, ready to run. */
      if (n->u.varray->length == 0)
	js_vm_make_static_string (vm, result_return, "", 0);
      else
	{
	  int len;
	  int glue_len = glue ? strlen (glue) : 1;

	  /* Estimate the result length. */
	  len = (n->u.varray->length * 5
		 + (n->u.varray->length - 1) * glue_len);

	  js_vm_make_string (vm, result_return, NULL, len);
	  result_return->u.vstring->len = 0;

	  /* Do the join. */
	  for (i = 0; i < n->u.varray->length; i++)
	    {
	      JSNode sitem;
	      int delta;

	      js_vm_to_string (vm, &n->u.varray->data[i], &sitem);
	      delta = sitem.u.vstring->len;

	      if (i + 1 < n->u.varray->length)
		delta += glue_len;

	      result_return->u.vstring->data
		= js_vm_realloc (vm, result_return->u.vstring->data,
				 result_return->u.vstring->len + delta);

	      memcpy (result_return->u.vstring->data
		      + result_return->u.vstring->len,
		      sitem.u.vstring->data,
		      sitem.u.vstring->len);
	      result_return->u.vstring->len += sitem.u.vstring->len;

	      if (i + 1 < n->u.varray->length)
		{
		  if (glue)
		    {
		      memcpy (result_return->u.vstring->data
			      + result_return->u.vstring->len,
			      glue, glue_len);
		      result_return->u.vstring->len += glue_len;
		    }
		  else
		    result_return->u.vstring->data
		      [result_return->u.vstring->len++] = ',';
		}
	    }
	}

      if (glue)
	js_free (glue);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_pop)
    {
      if (args->u.vinteger != 0)
	goto argument_error;

      if (n->u.varray->length == 0)
	result_return->type = JS_UNDEFINED;
      else
	{
	  JS_COPY (result_return, &n->u.varray->data[n->u.varray->length - 1]);
	  n->u.varray->length--;
	}
    }
  /* ********************************************************************** */
  else if (method == ctx->s_push)
    {
      int old_len;

      if (args->u.vinteger == 0)
	goto argument_error;

      old_len = n->u.varray->length;
      js_vm_expand_array (vm, n, n->u.varray->length + args->u.vinteger);

      for (i = 0; i < args->u.vinteger; i++)
	JS_COPY (&n->u.varray->data[old_len + i], &args[i + 1]);

      JS_COPY (result_return, &args[i]);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_reverse)
    {
      if (args->u.vinteger != 0)
	goto argument_error;

      for (i = 0; i < n->u.varray->length / 2; i++)
	{
	  JSNode tmp;

	  JS_COPY (&tmp, &n->u.varray->data[i]);
	  JS_COPY (&n->u.varray->data[i],
		   &n->u.varray->data[n->u.varray->length - i - 1]);
	  JS_COPY (&n->u.varray->data[n->u.varray->length - i - 1], &tmp);
	}
    }
  /* ********************************************************************** */
  else if (method == ctx->s_shift)
    {
      if (args->u.vinteger != 0)
	goto argument_error;

      if (n->u.varray->length == 0)
	result_return->type = JS_UNDEFINED;
      else
	{
	  JS_COPY (result_return, &n->u.varray->data[0]);
	  memmove (&n->u.varray->data[0], &n->u.varray->data[1],
		   (n->u.varray->length - 1) * sizeof (JSNode));
	  n->u.varray->length--;
	}
    }
  /* ********************************************************************** */
  else if (method == ctx->s_slice)
    {
      int start, end;

      if (args->u.vinteger < 1 || args->u.vinteger > 2)
	goto argument_error;

      if (args[1].type != JS_INTEGER)
	goto argument_type_error;

      start = args[1].u.vinteger;

      if (args->u.vinteger == 2)
	{
	  if (args[2].type != JS_INTEGER)
	    goto argument_type_error;

	  end = args[2].u.vinteger;
	}
      else
	end = n->u.varray->length;

      if (end < 0)
	end += n->u.varray->length;
      if (end < 0)
	end = start;

      js_vm_make_array (vm, result_return, end - start);

      /* Copy items. */
      for (i = 0; i < end - start; i++)
	JS_COPY (&result_return->u.varray->data[i],
		 &n->u.varray->data[start + i]);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_splice)
    {
      unsigned int new_length;
      unsigned int old_length;
      int delta;

      if (args->u.vinteger < 2)
	goto argument_error;
      if (args[1].type != JS_INTEGER || args[2].type != JS_INTEGER)
	goto argument_type_error;

      if (args[2].u.vinteger == 0 && args->u.vinteger == 2)
	/* No deletions: must specify at least one item to insert. */
	goto argument_error;

      old_length = new_length = n->u.varray->length;
      if (args[1].u.vinteger < new_length)
	{
	  if (args[2].u.vinteger > new_length - args[1].u.vinteger)
	    {
	      args[2].u.vinteger = new_length - args[1].u.vinteger;
	      new_length = args[1].u.vinteger;
	    }
	  else
	    new_length -= args[2].u.vinteger;
	}
      else
	{
	  new_length = args[1].u.vinteger;
	  args[2].u.vinteger = 0;
	}

      new_length += args->u.vinteger - 2;

      if (new_length > n->u.varray->length)
	js_vm_expand_array (vm, n, new_length);
      else
	/* Cut the array. */
	n->u.varray->length = new_length;

      /* Do the stuffs we must do. */

      /* Create the result array. */
      if (args[2].u.vinteger == 0)
	result_return->type = JS_UNDEFINED;
      else
	{
	  js_vm_make_array (vm, result_return, args[2].u.vinteger);
	  for (i = 0; i < args[2].u.vinteger; i++)
	    JS_COPY (&result_return->u.varray->data[i],
		     &n->u.varray->data[args[1].u.vinteger + i]);
	}

      /* Delete and move. */
      delta = args->u.vinteger - 2 - args[2].u.vinteger;
      memmove (&n->u.varray->data[args[1].u.vinteger + args[2].u.vinteger
				 + delta],
	       &n->u.varray->data[args[1].u.vinteger + args[2].u.vinteger],
	       (old_length - (args[1].u.vinteger + args[2].u.vinteger))
	       * sizeof (JSNode));

      /* Insert. */
      for (i = 0; i < args->u.vinteger - 2; i++)
	JS_COPY (&n->u.varray->data[args[1].u.vinteger + i], &args[i + 3]);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_sort)
    {
      MergesortCompFunc func;
      ArraySortCtx array_sort_ctx;
      void *func_ctx = NULL;	/* Initialized to keep compiler quiet. */

      if (args->u.vinteger == 0)
	{
	  func = sort_default_cmp_func;
	  func_ctx = vm;
	}
      else if (args->u.vinteger == 1)
	{
	  if (args[1].type != JS_FUNC && args[1].type != JS_BUILTIN)
	    goto argument_type_error;

	  func = sort_js_cmp_func;

	  /* Init context. */
	  array_sort_ctx.vm = vm;
	  array_sort_ctx.func = &args[1];

	  /* Init the argc part of the argument vector here. */
	  array_sort_ctx.argv[0].type = JS_INTEGER;
	  array_sort_ctx.argv[0].u.vinteger = 3;

	  func_ctx = &array_sort_ctx;
	}
      else
	goto argument_error;

      mergesort_r (n->u.varray->data, n->u.varray->length, sizeof (JSNode),
		   func, func_ctx);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_unshift)
    {
      int old_len;

      if (args->u.vinteger == 0)
	goto argument_error;

      old_len = n->u.varray->length;
      js_vm_expand_array (vm, n, n->u.varray->length + args->u.vinteger);

      memmove (&n->u.varray->data[args->u.vinteger], n->u.varray->data,
	       old_len * sizeof (JSNode));

      for (i = 0; i < args->u.vinteger; i++)
	JS_COPY (&n->u.varray->data[i], &args[args->u.vinteger - i]);

      result_return->type = JS_INTEGER;
      result_return->u.vinteger = n->u.varray->length;
    }
  /* ********************************************************************** */
  else
    return JS_PROPERTY_UNKNOWN;

  return JS_PROPERTY_FOUND;


  /*
   * Error handling.
   */

 argument_error:
  sprintf (vm->error, "Array.%s(): illegal amount of arguments",
	   js_vm_symname (vm, method));
  js_vm_error (vm);

 argument_type_error:
  sprintf (vm->error, "Array.%s(): illegal argument",
	   js_vm_symname (vm, method));
  js_vm_error (vm);

  /* NOTREACHED */
  return 0;
}
Exemple #12
0
void
js_vm_object_store_array (JSVirtualMachine *vm, JSObject *obj, JSNode *sel,
			  JSNode *value)
{
  if (sel->type == JS_INTEGER)
    {
      if (sel->u.vinteger < 0)
	{
	  sprintf (vm->error, "store_array: array index can't be nagative");
	  js_vm_error (vm);
	}
      if (sel->u.vinteger >= obj->num_props)
	{
	  /* Expand properties. */
	  obj->props = js_vm_realloc (vm, obj->props,
				      (sel->u.vinteger + 1)
				      * sizeof (JSProperty));

	  /* Init the possible gap. */
	  for (; obj->num_props <= sel->u.vinteger; obj->num_props++)
	    {
	      obj->props[obj->num_props].name = 0;
	      obj->props[obj->num_props].attributes = 0;
	      obj->props[obj->num_props].value.type = JS_UNDEFINED;
	    }
	}

      JS_COPY (&obj->props[sel->u.vinteger].value, value);
    }
  else if (sel->type == JS_STRING)
    {
      int pos;

      if (obj->hash == NULL)
	hash_create (vm, obj);

      pos = hash_lookup (obj, (char *) sel->u.vstring->data,
			 sel->u.vstring->len);
      if (pos < 0)
	{
	  /* It is undefined, define it. */
	  obj->props = js_vm_realloc (vm, obj->props,
				      (obj->num_props + 1)
				      * sizeof (JSProperty));

	  /*
	   * XXX if <sel> is a valid symbol, intern it and set symbol's
	   * name below.
	   */
	  obj->props[obj->num_props].name = JS_SYMBOL_NULL;
	  obj->props[obj->num_props].attributes = 0;
	  JS_COPY (&obj->props[obj->num_props].value, value);

	  hash_insert (vm, obj, (char *) sel->u.vstring->data,
		       sel->u.vstring->len, obj->num_props);

	  obj->num_props++;
	}
      else
	JS_COPY (&obj->props[pos].value, value);
    }
}