Пример #1
0
V7_PRIVATE void v7_freeval(struct v7 *v7, struct v7_val *v) {
  assert(v->ref_count > 0);
  if (--v->ref_count > 0) return;

  if (v->type == V7_TYPE_OBJ) {
    struct v7_prop *p, *tmp;
    for (p = v->props; p != NULL; p = tmp) {
      tmp = p->next;
      free_prop(v7, p);
    }
    v->props = NULL;
  }

  if (v7_is_class(v, V7_CLASS_ARRAY)) {
    struct v7_prop *p, *tmp;
    for (p = v->v.array; p != NULL; p = tmp) {
      tmp = p->next;
      free_prop(v7, p);
    }
    v->v.array = NULL;
  } else if (v->type == V7_TYPE_STR && (v->flags & V7_STR_ALLOCATED)) {
    free(v->v.str.buf);
  } else if (v7_is_class(v, V7_CLASS_REGEXP) && (v->flags & V7_STR_ALLOCATED)) {
    free(v->v.regex);
  } else if (v7_is_class(v, V7_CLASS_FUNCTION)) {
    if ((v->flags & V7_STR_ALLOCATED) && (v->flags & V7_JS_FUNC)) {
      free(v->v.func.source_code);
      v7_freeval(v7, v->v.func.var_obj);
    }
  }

  if (v->flags & V7_VAL_ALLOCATED) {
    v->flags &= ~V7_VAL_ALLOCATED;
    v->flags |= ~V7_VAL_DEALLOCATED;
    memset(v, 0, sizeof(*v));
#ifdef V7_CACHE_OBJS
    v->next = v7->free_values;
    v7->free_values = v;
#else
    free(v);
#endif
  }
}
Пример #2
0
V7_PRIVATE struct v7_prop *v7_get2(struct v7_val *obj, const struct v7_val *key,
                              int own_prop) {
  struct v7_prop *m;
  for (; obj != NULL; obj = obj->proto) {
    if (v7_is_class(obj, V7_CLASS_ARRAY) && key->type == V7_TYPE_NUM) {
      int i = (int) key->v.num;
      for (m = obj->v.array; m != NULL; m = m->next) {
        if (i-- == 0) return m;
      }
    } else if (obj->type == V7_TYPE_OBJ) {
      for (m = obj->props; m != NULL; m = m->next) {
        if (cmp(m->key, key) == 0) return m;
      }
    }
    if (own_prop) break;
    if (obj->proto == obj) break;
  }
  return NULL;
}
Пример #3
0
Файл: string.c Проект: mwanna/v7
static void Str_match(struct v7_c_func_arg *cfa) {
  struct slre_cap caps[100];
  const struct v7_string *s = &cfa->this_obj->v.str;
  int i, n;

  cfa->result->type = V7_TYPE_NULL;
  memset(caps, 0, sizeof(caps));

  if (cfa->num_args == 1 &&
      v7_is_class(cfa->args[0], V7_CLASS_REGEXP) &&
      (n = slre_match(cfa->args[0]->v.regex, s->buf, s->len,
                      caps, ARRAY_SIZE(caps) - 1, 0)) > 0) {
    v7_set_class(cfa->result, V7_CLASS_ARRAY);
    v7_append(cfa->v7, cfa->result,
              v7_mkv(cfa->v7, V7_TYPE_STR, s->buf, (long) n, 1));
    for (i = 0; i < (int) ARRAY_SIZE(caps); i++) {
      if (caps[i].len == 0) break;
      v7_append(cfa->v7, cfa->result,
                v7_mkv(cfa->v7, V7_TYPE_STR, caps[i].ptr, (long) caps[i].len, 1));
    }
  }
}
Пример #4
0
V7_PRIVATE int is_bool(const struct v7_val *v) {
  obj_sanity_check(v);
  return v->type == V7_TYPE_BOOL || v7_is_class(v, V7_CLASS_BOOLEAN);
}
Пример #5
0
V7_PRIVATE int is_num(const struct v7_val *v) {
  obj_sanity_check(v);
  return v->type == V7_TYPE_NUM || v7_is_class(v, V7_CLASS_NUMBER);
}
Пример #6
0
V7_PRIVATE int is_string(const struct v7_val *v) {
  obj_sanity_check(v);
  return v->type == V7_TYPE_STR || v7_is_class(v, V7_CLASS_STRING);
}
Пример #7
0
V7_PRIVATE enum v7_err Str_replace(struct v7_c_func_arg *cfa) {
#define v7 (cfa->v7) /* Needed for TRY() macro below */
  struct v7_val *result = v7_push_new_object(v7);
  const char *out_str = cfa->this_obj->v.str.buf;
  uint8_t own = 1;
  size_t out_len = cfa->this_obj->v.str.len;
  int old_sp = v7->sp;

  if (cfa->num_args > 1) {
    const char *const str_end =
        cfa->this_obj->v.str.buf + cfa->this_obj->v.str.len;
    char *p = cfa->this_obj->v.str.buf;
    uint32_t out_sub_num = 0;
    struct v7_val *re = cfa->args[0], *str_func = cfa->args[1], *arr = NULL;
    struct re_tok out_sub[V7_RE_MAX_REPL_SUB], *ptok = out_sub;
    struct Resub loot;
    TRY(check_str_re_conv(v7, &re, 1));
    TRY(regex_check_prog(re));
    if (v7_is_class(str_func, V7_CLASS_FUNCTION)) {
      arr = v7_push_new_object(v7);
      v7_set_class(arr, V7_CLASS_ARRAY);
      TRY(v7_push(v7, str_func));
    } else
      TRY(check_str_re_conv(v7, &str_func, 0));

    out_len = 0;
    do {
      int i;
      if (re_exec(re->v.str.prog, re->fl.fl, p, &loot)) break;
      if (p != loot.sub->start) {
        ptok->start = p;
        ptok->end = loot.sub->start;
        ptok++;
        out_len += loot.sub->start - p;
        out_sub_num++;
      }

      if (NULL != arr) { /* replace function */
        Rune rune;
        int old_sp = v7->sp, utf_shift = 0;
        struct v7_val *rez_str;
        for (i = 0; i < loot.subexpr_num; i++)
          v7_push_string(v7, loot.sub[i].start,
                         loot.sub[i].end - loot.sub[i].start, 1);
        for (i = 0; p + i < loot.sub[0].start;
             i += chartorune(&rune, p + i), utf_shift++)
          ;
        TRY(push_number(v7, utf_shift));
        TRY(v7_push(v7, cfa->this_obj));
        rez_str = v7_call(v7, cfa->this_obj, loot.subexpr_num + 2);
        TRY(check_str_re_conv(v7, &rez_str, 0));
        if (rez_str->v.str.len) {
          ptok->start = rez_str->v.str.buf;
          ptok->end = rez_str->v.str.buf + rez_str->v.str.len;
          ptok++;
          out_len += rez_str->v.str.len;
          out_sub_num++;
          v7_append(v7, arr, rez_str);
        }
        TRY(inc_stack(v7, old_sp - v7->sp));
      } else { /* replace string */
        struct Resub newsub;
        re_rplc(&loot, p, str_func->v.str.buf, &newsub);
        for (i = 0; i < newsub.subexpr_num; i++) {
          ptok->start = newsub.sub[i].start;
          ptok->end = newsub.sub[i].end;
          ptok++;
          out_len += newsub.sub[i].end - newsub.sub[i].start;
          out_sub_num++;
        }
      }
      p = (char *)loot.sub->end;
    } while (re->fl.fl.re_g && p < str_end);
    if (p < str_end) {
      ptok->start = p;
      ptok->end = str_end;
      ptok++;
      out_len += str_end - p;
      out_sub_num++;
    }
    out_str = malloc(out_len + 1);
    CHECK(out_str, V7_OUT_OF_MEMORY);
    ptok = out_sub;
    p = (char *)out_str;
    do {
      size_t ln = ptok->end - ptok->start;
      memcpy(p, ptok->start, ln);
      p += ln;
      ptok++;
    } while (--out_sub_num);
    *p = '\0';
    own = 0;
  }
  TRY(inc_stack(v7, old_sp - v7->sp));
  v7_init_str(result, out_str, out_len, own);
  result->fl.fl.str_alloc = 1;
  return V7_OK;
#undef v7
}
Пример #8
0
static const char *test_v7_exec(void) {
  struct v7 *v7 = v7_create();

  ASSERT(v7_exec(v7, "") == V7_OK);
  ASSERT(v7_exec(v7, "-2;") == V7_OK);
  ASSERT(check_num(v7, -2.0));
  ASSERT(v7_exec(v7, "3 + 4") == V7_OK);
  ASSERT(check_num(v7, 7.0));
  ASSERT(v7_exec(v7, "123.456") == V7_OK);
  ASSERT(check_num(v7, 123.456));
  ASSERT(v7_exec(v7, "NaN") == V7_OK);
  ASSERT(check_num(v7, NAN));

  // TODO: fix infinity handling under MSVC6
#ifndef _WIN32
  ASSERT(v7_exec(v7, "Infinity") == V7_OK);
  ASSERT(check_num(v7, INFINITY));
  ASSERT(v7_exec(v7, "-Infinity") == V7_OK);
  ASSERT(check_num(v7, -INFINITY));
#endif

  ASSERT(v7_exec(v7, "2()") == V7_CALLED_NON_FUNCTION);
  ASSERT(v7_exec(v7, " 15 +	2 \r\n * 2  / 1 - 3 * 4 ; ") == V7_OK);

  ASSERT(v7_exec(v7, "( (5  ) );") == V7_OK);
  ASSERT(check_num(v7, 5.0));

  ASSERT(v7_exec(v7, "(2 + (12 / 4));") == V7_OK);
  ASSERT(v7_top(v7)[-1]->type == V7_TYPE_NUM);
  ASSERT(v7_top(v7)[-1]->v.num == 5.0);

  ASSERT(v7_exec(v7, "1;2 7") == V7_OK);
  ASSERT(check_num(v7, 7.0));
  ASSERT(v7_exec(v7, "a + 5") == V7_TYPE_ERROR);

  ASSERT(v7_exec(v7, "print();") == V7_OK);
  ASSERT(v7_exec(v7, "print(this);") == V7_OK);

  ASSERT(v7_exec(v7, "a = 7;") == V7_OK);
  ASSERT(check_num(v7, 7.0));
  ASSERT(v7_exec(v7, "print(this);") == V7_OK);

  ASSERT(v7_exec(v7, "b = a + 3;") == V7_OK);
  ASSERT(check_num(v7, 10.0));
  ASSERT(v7_exec(v7, "print(this);") == V7_OK);

  ASSERT(v7_exec(v7, "c = b * (a + 3) / 2;") == V7_OK);
  ASSERT(check_num(v7, 50.0));
  ASSERT(v7_exec(v7, "print(this);") == V7_OK);

  ASSERT(v7_exec(v7, "var x = 12 + 2 - a + b+ 3 / 4 * a;") == V7_OK);
  ASSERT(v7_exec(v7, "b + 2; x + 3 + 1 z = x -2;") == V7_OK);
  ASSERT(v7_exec(v7, "x; var y, z;") == V7_OK);
  ASSERT(v7_exec(v7, "1 2 3") == V7_OK);

  ASSERT(v7_exec(v7, "var k = true;") == V7_OK);
  ASSERT(v7_top(v7)[-1]->type == V7_TYPE_BOOL);
  ASSERT(v7_top(v7)[-1]->v.num != 0.0);

  ASSERT(v7_exec(v7, "var blah = 'kuku';") == V7_OK);
  ASSERT(v7_top(v7)[-1]->type == V7_TYPE_STR);

  // Test that k.y does exist
  ASSERT(v7_exec(v7, "k = { y: 17 };") == V7_OK);
  ASSERT(v7_exec(v7, "k.y") == V7_OK);
  ASSERT(check_num(v7, 17.0));
  v7_exec(v7, "print(this);");

  // Delete k.y and make sure it's gone
  ASSERT(v7_exec(v7, "delete k.y;") == V7_OK);
  ASSERT(v7_exec(v7, "k.y;") == V7_OK);
  ASSERT(v7_top(v7)[-1]->type == V7_TYPE_UNDEF);
  ASSERT(v7_sp(v7) == 1);
  ASSERT(v7_exec(v7, "delete b; b;") == V7_OK);
  ASSERT(v7_top(v7)[-1]->type == V7_TYPE_UNDEF);
  ASSERT(v7_sp(v7) == 1);

  ASSERT(v7_exec(v7, "k = { key1: {x:3}, key2: ':-)', y: 5 };") == V7_OK);
  ASSERT(v7_top(v7)[-1]->type == V7_TYPE_OBJ);
  ASSERT(v7_sp(v7) == 1);

  ASSERT(v7_exec(v7, "k.x = 47;") == V7_OK);
  ASSERT(v7_exec(v7, "k.qwe = { foo: 5 };") == V7_OK);
  v7_exec(v7, "print(k);");
  ASSERT(v7_exec(v7, "k.qwe.foo = 15;") == V7_OK);
  v7_exec(v7, "print(k);");

  ASSERT(v7_exec(v7, "k.key1.x + 4") == V7_OK);
  ASSERT(check_num(v7, 7.0));

  ASSERT(v7_exec(v7, "k.foo") == V7_OK);
  ASSERT(v7_top(v7)[-1]->type == V7_TYPE_UNDEF);

  ASSERT(v7_exec(v7, "var z = 'key1'; k[z]['x']") == V7_OK);
  ASSERT(check_num(v7, 3.0));

  ASSERT(v7_exec(v7, "var stk = 1;") == V7_OK);
  ASSERT(check_num(v7, 1.0));

  ASSERT(v7_exec(v7, "var f1 = function(x, y) { } ; ") == V7_OK);
  ASSERT(v7_sp(v7) > 0);
  ASSERT(v7_top(v7)[-1]->type == V7_TYPE_OBJ);
  ASSERT(memcmp(v7_top(v7)[-1]->v.func.source_code, "(x, y) { } ", 10) == 0);

  ASSERT(v7_exec(v7, "var f1 = function(x, y) { return x * y; };") == V7_OK);
  ASSERT(v7_is_class(v7_top(v7)[-1], V7_CLASS_FUNCTION));
  ASSERT(v7_exec(v7, "f1(2, 3)") == V7_OK);
  ASSERT(check_num(v7, 6.0));
  ASSERT(v7_exec(v7, "f1(12, 4) + 1;") == V7_OK);
  ASSERT(check_num(v7, 49.0));
  ASSERT(v7_exec(v7, "f1(12, 4) * 2;") == V7_OK);
  ASSERT(check_num(v7, 96.0));

  ASSERT(v7_exec(v7, "f = function(x,y,z) {print(this);};") == V7_OK);
  ASSERT(v7_sp(v7) == 1);
  ASSERT(v7_exec(v7, "f();") == V7_OK);
  ASSERT(v7_exec(v7, "f({});") == V7_OK);
  ASSERT(v7_exec(v7, "f(1, 2);") == V7_OK);
  ASSERT(v7_exec(v7, "f(123, {});") == V7_OK);

  ASSERT(v7_exec(v7, "if (0) f1 = 2; ") == V7_OK);
  ASSERT(v7_exec(v7, "if (5) { f1 = 3; f2 = function(){}; } ") == V7_OK);

  ASSERT(v7_exec(v7, "0 ? 1 : 2;") == V7_OK);
  ASSERT(check_num(v7, 2.0));

  ASSERT(v7_exec(v7, "k = true ? 1 : 2;") == V7_OK);
  ASSERT(check_num(v7, 1.0));

  ASSERT(v7_exec(v7, "var f = function(){var x=12; return x + 1;};") == V7_OK);
  ASSERT(v7_sp(v7) > 0);

  ASSERT(v7_exec(v7, "k = f(1,2,3);") == V7_OK);
  ASSERT(check_num(v7, 13.0));

  ASSERT(v7_exec(v7, "(function() { return f() + 7; })()") == V7_OK);
  ASSERT(check_num(v7, 20.0));

  ASSERT(v7_exec(v7, "var a = 1; if (a == 1) { a = 2; }; a;") == V7_OK);
  ASSERT(check_num(v7, 2.0));

  ASSERT(v7_exec(v7, "var a = 'foo'; a == 'foo';") == V7_OK);
  ASSERT(check_bool(v7, 1.0));

  ASSERT(v7_exec(v7, "a = { x: function(p) { print(this); } }") == V7_OK);
  ASSERT(v7_exec(v7, "a.x(2);") == V7_OK);

  ASSERT(v7_exec(v7, "74.toString()") == V7_OK);
  ASSERT(check_str(v7, "74"));
  ASSERT(v7_exec(v7, "'hello'.length") == V7_OK);
  ASSERT(check_num(v7, 5.0));

  ASSERT(v7_exec(v7, "k = { x : function() { if (1) 2; } }") == V7_OK);

  ASSERT(v7_exec(v7, "'foo' + 'bar'") == V7_OK);
  ASSERT(check_str(v7, "foobar"));

  ASSERT(v7_exec(v7, "var x = [1, 'foo', true, 7];") == V7_OK);
  ASSERT(v7_exec(v7, "x.length") == V7_OK);
  ASSERT(check_num(v7, 4.0));
  ASSERT(v7_exec(v7, "x[1]") == V7_OK);
  ASSERT(check_str(v7, "foo"));

  ASSERT(v7_exec(v7, "var f1 = function() { 1; };") == V7_OK);
  ASSERT(v7_exec(v7, "var f2 = function(x) { if (x) return x; };") == V7_OK);
  ASSERT(v7_exec(v7, "f1()") == V7_OK);
  ASSERT(v7->sp == 1 && v7->stack[0]->type == V7_TYPE_UNDEF);
  ASSERT(v7_exec(v7, "f2(false)") == V7_OK);
  ASSERT(v7->sp == 1 && v7->stack[0]->type == V7_TYPE_UNDEF);
  ASSERT(v7_exec(v7, "f2(17)") == V7_OK);
  ASSERT(check_num(v7, 17.0));
  ASSERT(v7_exec(v7, "f2(true)") == V7_OK);
  ASSERT(check_bool(v7, 1.0));

  ASSERT(v7_exec(v7, "1 <= 2 ? 7 : 8") == V7_OK);
  ASSERT(check_num(v7, 7.0));

  ASSERT(v7_exec(v7, "function a (t) { return t * t }; ") == V7_OK);
  ASSERT(v7_exec(v7, "a(2)") == V7_OK);
  ASSERT(check_num(v7, 4.0));
  ASSERT(v7_exec(v7, "a(0)") == V7_OK);
  ASSERT(check_num(v7, 0.0));

  ASSERT(v7_exec(v7, "function fac(x) { "
         "return x <= 1 ? 1 : x * fac(x - 1); }") == V7_OK);
  ASSERT(v7_exec(v7, "fac(1)") == V7_OK);
  ASSERT(check_num(v7, 1.0));
  ASSERT(v7_exec(v7, "fac(5)") == V7_OK);
  ASSERT(check_num(v7, 120.0));
  ASSERT(v7_exec(v7, "fac(20)") == V7_OK);

  ASSERT(v7_exec(v7, "function qq(a,b) { return a + b; }") == V7_OK);
  ASSERT(v7_exec(v7, "qq(1,2)") == V7_OK);
  ASSERT(check_num(v7, 3.0));

  ASSERT(v7_exec(v7, "1 < 2 == 2 < 3") == V7_OK);
  ASSERT(check_bool(v7, 1.0));

  ASSERT(v7_exec(v7, "5 % 3 * 3") == V7_OK);
  ASSERT(check_num(v7, 6.0));
  ASSERT(v7_exec(v7, "76 & 13") == V7_OK);
  ASSERT(check_num(v7, 12.0));
  ASSERT(v7_exec(v7, "34325 ^ 190992 & 74832") == V7_OK);
  ASSERT(check_num(v7, 42501.0));

  ASSERT(v7_exec(v7, "a = 12;") == V7_OK);
  ASSERT(v7_exec(v7, "a += 44; a;") == V7_OK);
  ASSERT(check_num(v7, 56.0));
  ASSERT(v7_exec(v7, "a -= a / 2; a;") == V7_OK);
  ASSERT(check_num(v7, 28.0));
  ASSERT(v7_exec(v7, "a *= 0.5; a;") == V7_OK);
  ASSERT(check_num(v7, 14.0));
#ifndef _WIN32
  ASSERT(v7_exec(v7, "a /= 0; a;") == V7_OK);
  ASSERT(check_num(v7, INFINITY));
#endif

  ASSERT(v7_exec(v7, "!5") == V7_OK);
  ASSERT(check_bool(v7, 0.0));
  ASSERT(v7_exec(v7, "!''") == V7_OK);
  ASSERT(check_bool(v7, 1.0));
  ASSERT(v7_exec(v7, "1 != 2") == V7_OK);
  ASSERT(check_bool(v7, 1.0));
  ASSERT(v7_exec(v7, "7 >= 0") == V7_OK);
  ASSERT(check_bool(v7, 1.0));

  ASSERT(v7_exec(v7, "if (false) 3; ") == V7_OK);
  ASSERT(v7_exec(v7, "if (true) { if (1) {2;} 5; } ") == V7_OK);
  ASSERT(check_num(v7, 5.0));
  ASSERT(v7_exec(v7, "if ('') 3; ") == V7_OK);
  ASSERT(v7_exec(v7, "if ('0') 9; ") == V7_OK);
  ASSERT(check_num(v7, 9.0));
  ASSERT(v7_exec(v7, "if (false) 1; else 3;") == V7_OK);
  ASSERT(check_num(v7, 3.0));
  ASSERT(v7_exec(v7, "if (false) 1; else if (0) { 3 } else { 2 }") == V7_OK);
  ASSERT(check_num(v7, 2.0));
  ASSERT(v7_exec(v7, "if (false) 1; else if (1) { 3 } else { 2 }") == V7_OK);
  ASSERT(check_num(v7, 3.0));

  ASSERT(v7_exec(v7, "a = 32; 2 + a++;") == V7_OK);
  ASSERT(check_num(v7, 35.0));

  ASSERT(v7_exec(v7, "print(['hi', 1, true, null, /\\s+/])") == V7_OK);

  ASSERT(v7_exec(v7, "a = {};") == V7_OK);
  ASSERT(v7_exec(v7, "a.foo = function(x) { var y = "
                 "x.substr(1).split() }") == V7_OK);

  ASSERT(v7_exec(v7, "typeof 2") == V7_OK);
  ASSERT(check_str(v7, "number"));

  v7_destroy(&v7);
  return NULL;
}