Exemplo n.º 1
0
int duk_bi_error_prototype_to_string(duk_context *ctx) {
	/* FIXME: optimize with more direct internal access */

	duk_push_this(ctx);
	if (!duk_is_object(ctx, -1)) {
		goto type_error;
	}

	/* [ ... this ] */

	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME);
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		duk_push_string(ctx, "Error");
	} else {
		duk_to_string(ctx, -1);
	}

	/* [ ... this name ] */

	/* FIXME: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
	 * accident or are they actually needed?  The first ToString()
	 * could conceivably return 'undefined'.
	 */
	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		duk_push_string(ctx, "");
	} else {
		duk_to_string(ctx, -1);
	}

	/* [ ... this name message ] */

	if (duk_get_length(ctx, -2) == 0) {
		/* name is empty -> return message */
		return 1;
	}
	if (duk_get_length(ctx, -1) == 0) {
		/* message is empty -> return name */
		duk_pop(ctx);
		return 1;
	}
	duk_push_string(ctx, ": ");
	duk_insert(ctx, -2);  /* ... name ': ' message */
	duk_concat(ctx, 3);

	return 1;

 type_error:
	return DUK_RET_TYPE_ERROR;
}
Exemplo n.º 2
0
int test_1(duk_context *ctx) {
	int i, n;

	duk_set_top(ctx, 0);

	/* simple */
	duk_push_string(ctx, "   foo   \n");

	/*
	 *  >>> u'\u00a0\ufeff'.encode('utf-8').encode('hex')
	 *  'c2a0efbbbf'
	 *
	 *  >>> u'\u2028\u2029'.encode('utf-8').encode('hex')
	 *  'e280a8e280a9'
	 */

	duk_push_string(ctx, "\xc2\xa0\xef\xbb\xbf\x0a\xe2\x80\xa8\xe2\x80\xa9"
	                     "foo bar"
	                     "\xc2\xa0\xef\xbb\xbf\x0a\xe2\x80\xa8\xe2\x80\xa9");


	n = duk_get_top(ctx);
	for (i = 0; i < n; i++) {
		size_t sz;

		sz = duk_get_length(ctx, i);
		duk_trim(ctx, i);
		printf("%d: clen=%d, trimmed='%s'\n",
		       i, (int) sz, duk_get_string(ctx, i));
	}

	printf("final top: %d\n", duk_get_top(ctx));
	return 0;
}
Exemplo n.º 3
0
static duk_ret_t test_basic(duk_context *ctx) {
	char buf[65536 + 1024];
	duk_size_t fmt_len, i;
	double len_sum = 0.0;

	for (fmt_len = 0;
	     fmt_len <= 65536;
	     fmt_len ++) {
		for (i = 0; i < fmt_len; i++) {
			buf[i] = 'x';
		}
		buf[fmt_len + 0] = '%';
		buf[fmt_len + 1] = 'd';
		buf[fmt_len + 2] = '\0';

		duk_push_sprintf(ctx, buf, 123);
		len_sum += (double) duk_get_length(ctx, -1);  /* trivial "checksum" */
		duk_pop(ctx);
	}

	/* Length sequence is 3, 4, ..., 65539 ->
	 * (65539 + 3)/2 * (65539 - 3 + 1) = 2147713027
	 *
	 * >>> res = 0
	 * >>> for i in xrange(0, 65536+1):
	 * ...   res += len( (('x' * i) + '%d') % 123 )
	 * ...
	 * >>> res
	 * 2147713027
	 */

	printf("length sum: %lf\n", len_sum);
	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Exemplo n.º 4
0
/* Debug print which visualizes the qsort partitioning process. */
static void duk__debuglog_qsort_state(duk_context *ctx, int lo, int hi, int pivot) {
	char buf[4096];
	char *ptr = buf;
	int i, n;
	n = duk_get_length(ctx, 1);
	if (n > 4000) {
		n = 4000;
	}
	*ptr++ = '[';
	for (i = 0; i < n; i++) {
		if (i == pivot) {
			*ptr++ = '|';
		} else if (i == lo) {
			*ptr++ = '<';
		} else if (i == hi) {
			*ptr++ = '>';
		} else if (i >= lo && i <= hi) {
			*ptr++ = '-';
		} else {
			*ptr++ = ' ';
		}
	}
	*ptr++ = ']';
	*ptr++ = '\0';

	DUK_DDD(DUK_DDDPRINT("%s   (lo=%d, hi=%d, pivot=%d)", buf, lo, hi, pivot));
}
Exemplo n.º 5
0
int* getIntArray(duk_context *ctx, int stackIndex) {
	static int* result = NULL;

	if(duk_is_array(ctx, stackIndex)) {
    int resultLen = duk_get_length(ctx, stackIndex);

    result = (int*)malloc( resultLen * sizeof(int) );
    memset(result,0,resultLen);

    duk_enum(ctx, stackIndex, DUK_ENUM_ARRAY_INDICES_ONLY);


		// NOT stackIndex because waits enumIndex that is -1
		int idx=0;
		while (duk_next(ctx, -1, 1)) {
			 // in JS/duktape toto[1] <=> toto["1"]
			 // that's why keys are strings
			 const char* k = duk_to_string(ctx, -2);
			 int v = duk_to_int(ctx, -1);
		   //printf("key=%s, value=%d\n", k, v);
			 result[idx++] = v;
		   duk_pop_2(ctx);
		}
		duk_pop(ctx); // duk_enum

  } else {
  	printf("Found NO array\n");
  }

  return result;
}
Exemplo n.º 6
0
duk_ret_t JavaScriptObject::finalizer(duk_context* ctx) {
    // Remove this pointers from the JS object's property.
    if (duk_get_prop_string(ctx, -1, WRAPPER_THIS_PROP_NAME)) {
        const duk_size_t length = duk_get_length(ctx, -1);
        for (duk_uarridx_t i = 0; i < length; ++i) {
            duk_get_prop_index(ctx, -1, i);

            JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(duk_get_pointer(ctx, -1));
            if (obj && obj->m_instance) {
                // Null out the instance pointer - it's been garbage collected!
                obj->m_instance = nullptr;

                if (obj->m_nextFinalizer) {
                    // Continue with the next finalizer in the chain.
                    obj->m_nextFinalizer(ctx);
                }
            }
            duk_pop(ctx);
        }
    }

    // Pop the array (or undefined if there was none).
    duk_pop(ctx);

    return 0;
}
Exemplo n.º 7
0
/* Debug print which visualizes the qsort partitioning process. */
DUK_LOCAL void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
	char buf[4096];
	char *ptr = buf;
	duk_int_t i, n;
	n = (duk_int_t) duk_get_length(ctx, 1);
	if (n > 4000) {
		n = 4000;
	}
	*ptr++ = '[';
	for (i = 0; i < n; i++) {
		if (i == pivot) {
			*ptr++ = '|';
		} else if (i == lo) {
			*ptr++ = '<';
		} else if (i == hi) {
			*ptr++ = '>';
		} else if (i >= lo && i <= hi) {
			*ptr++ = '-';
		} else {
			*ptr++ = ' ';
		}
	}
	*ptr++ = ']';
	*ptr++ = '\0';

	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
}
Exemplo n.º 8
0
DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
	/* XXX: optimize with more direct internal access */

	duk_push_this(ctx);
	(void) duk_require_hobject_promote_mask(ctx, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);

	/* [ ... this ] */

	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME);
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		duk_push_string(ctx, "Error");
	} else {
		duk_to_string(ctx, -1);
	}

	/* [ ... this name ] */

	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
	 * accident or are they actually needed?  The first ToString()
	 * could conceivably return 'undefined'.
	 */
	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		duk_push_string(ctx, "");
	} else {
		duk_to_string(ctx, -1);
	}

	/* [ ... this name message ] */

	if (duk_get_length(ctx, -2) == 0) {
		/* name is empty -> return message */
		return 1;
	}
	if (duk_get_length(ctx, -1) == 0) {
		/* message is empty -> return name */
		duk_pop(ctx);
		return 1;
	}
	duk_push_string(ctx, ": ");
	duk_insert(ctx, -2);  /* ... name ': ' message */
	duk_concat(ctx, 3);

	return 1;
}
Exemplo n.º 9
0
void ObjectList::AddObject(void *val) {
    Isolate *isolate = Isolate::GetCurrent();
    duk_context *ctx = isolate->GetDukContext();

    duk_push_heapptr(ctx, list_ptr_);
    duk_push_heapptr(ctx, val);
    duk_size_t len = duk_get_length(ctx, -1);
    duk_put_prop_index(ctx, -2, (duk_uarridx_t) len);
    duk_pop(ctx);
}
Exemplo n.º 10
0
static void print_top(duk_context *ctx) {
	duk_size_t clen = 0;
	if (duk_is_string(ctx, -1)) {
		clen = duk_get_length(ctx, -1);
	}
	printf("top=%ld type=%ld bool=%d num=%.6lf clen=%ld str='%s' str-is-NULL=%d ptr-is-NULL=%d\n",
	       (long) duk_get_top(ctx), (long) duk_get_type(ctx, -1), (int) duk_get_boolean(ctx, -1),
	       (double) duk_get_number(ctx, -1), (long) clen, duk_get_string(ctx, -1),
	       (duk_get_string(ctx, -1) ? 0 : 1),
	       (duk_get_pointer(ctx, -1) ? 0 : 1));
}
Exemplo n.º 11
0
/*
 * Looks for an interface that defines a specific member.
 *
 * TODO - check for ambiguity - same member defined on multiple interfaces
 */
static const char* FindInterfaceForMember(duk_context* ctx, duk_idx_t mbrIdx, const char** member)
{
    const char* iface = NULL;
    uint8_t found = FALSE;
    size_t numInterfaces;
    duk_idx_t listIdx;

    duk_get_prop_string(ctx, -1, "interfaces");
    numInterfaces = duk_get_length(ctx, -1);
    listIdx = AJS_GetAllJoynProperty(ctx, "interfaceDefinition");

    if (duk_is_object(ctx, mbrIdx)) {
        /*
         * Expect an object of form { member:"org.foo.interface" }
         */
        duk_enum(ctx, mbrIdx, DUK_ENUM_OWN_PROPERTIES_ONLY);
        if (!duk_next(ctx, -1, 1)) {
            duk_error(ctx, DUK_ERR_TYPE_ERROR, "Require object of form { 'member-name':'interface-name' }");
        }
        iface = duk_require_string(ctx, -1);
        if (!AJ_StringFindFirstOf(iface, ".") == -1) {
            duk_error(ctx, DUK_ERR_TYPE_ERROR, "Interface name '%s' is not a dotted name", iface);
        }
        *member = duk_require_string(ctx, -2);
        duk_get_prop_string(ctx, listIdx, iface);
        if (duk_is_undefined(ctx, -1)) {
            duk_error(ctx, DUK_ERR_REFERENCE_ERROR, "Unknown interface: '%s'", iface);
        }
        found = duk_has_prop_string(ctx, -1, *member);
        duk_pop_n(ctx, 4);
    } else {
        size_t i;
        /*
         * Expect a string
         */
        *member = duk_require_string(ctx, mbrIdx);
        for (i = 0; !found && (i < numInterfaces); ++i) {
            duk_get_prop_index(ctx, -2, i);
            iface = duk_require_string(ctx, -1);
            duk_get_prop_string(ctx, listIdx, iface);
            /*
             * See if the requested member exists on this interface
             */
            found = duk_has_prop_string(ctx, -1, *member);
            duk_pop_2(ctx);
        }
    }
    duk_pop_2(ctx);
    if (!found) {
        duk_error(ctx, DUK_ERR_REFERENCE_ERROR, "Unknown member: '%s'", *member);
    }
    return iface;
}
Exemplo n.º 12
0
static void test_2(duk_context *ctx, int fmt_len, va_list ap) {
	int i;

	for (i = 0; i < fmt_len; i++) {
		buf[i] = 'x';
	}
	buf[fmt_len + 0] = '%';
	buf[fmt_len + 1] = 'd';
	buf[fmt_len + 2] = '\0';

	duk_push_vsprintf(ctx, buf, ap);
	len_sum += (double) duk_get_length(ctx, -1);  /* trivial "checksum" */
	duk_pop(ctx);
}
Exemplo n.º 13
0
/*
 * Serializes various data types into a buffer. Leaves the buffer on the top of the stack.
 */
static uint8_t* SerializeToBuffer(duk_context* ctx, duk_idx_t idx, duk_size_t* sz)
{
    uint8_t* ptr;

    switch (duk_get_type(ctx, idx)) {
    case DUK_TYPE_BUFFER:
        duk_dup(ctx, idx);
        ptr = duk_get_buffer(ctx, -1, sz);
        break;

    case DUK_TYPE_BOOLEAN:
        ptr = duk_push_fixed_buffer(ctx, 1);
        ptr[0] = duk_get_boolean(ctx, idx);
        *sz = 1;
        break;

    case DUK_TYPE_NUMBER:
        ptr = duk_push_fixed_buffer(ctx, 1);
        ptr[0] = duk_get_int(ctx, idx);
        *sz = 1;
        break;

    case DUK_TYPE_STRING:
        duk_dup(ctx, idx);
        ptr = duk_to_fixed_buffer(ctx, -1, sz);
        break;

    case DUK_TYPE_OBJECT:
        if (duk_is_array(ctx, idx)) {
            duk_idx_t i;
            duk_idx_t len = duk_get_length(ctx, idx);
            ptr = duk_push_fixed_buffer(ctx, len);
            for (i = 0; i < len; ++i) {
                duk_get_prop_index(ctx, idx, i);
                ptr[i] = duk_require_uint(ctx, -1);
                duk_pop(ctx);
            }
            *sz = len;
        } else {
            duk_error(ctx, DUK_ERR_TYPE_ERROR, "Can only serialize arrays of numbers");
        }
        break;

    default:
        duk_error(ctx, DUK_ERR_TYPE_ERROR, "Cannot serialize");
        break;
    }
    return ptr;
}
Exemplo n.º 14
0
static int test_1(duk_context *ctx) {
    duk_size_t i, n;

    /* Simple test, intentional out-of-bounds access at the end. */

    duk_eval_string(ctx, "'foo\\u1234bar\\u00a0quux\\u0000baz'");

    n = duk_get_length(ctx, -1) + 3;  /* access 3 times out-of-bounds */
    for (i = 0; i < n; i++) {
        printf("i=%ld, n=%ld, charcode=%d\n", (long) i, (long) n, (int) duk_char_code_at(ctx, -1, i));
    }

    duk_pop(ctx);
    return 0;
}
Exemplo n.º 15
0
static void dump_string(duk_context *ctx) {
	const char *buf;
	duk_size_t i, len;

	buf = duk_get_lstring(ctx, -1, &len);
	printf("blen=%lu, clen=%lu, str=\"", (unsigned long) len, (unsigned long) duk_get_length(ctx, -1));
	for (i = 0; i < len; i++) {
		char c = buf[i];
		if (c >= 0x20 && c <= 0x7e) {
			printf("%c", c);
		} else {
			printf("\\x%02x", ((int) c) & 0xff);
		}
	}
	printf("\"\n");

	duk_pop(ctx);
}
Exemplo n.º 16
0
Vector<String> GetStringVector(duk_context* ctx, duk_idx_t stackIndex)
{
    Vector<String> ret;

    if (duk_is_object(ctx, stackIndex))
    {
        duk_size_t len = duk_get_length(ctx, stackIndex);
        for (duk_size_t i = 0; i < len; ++i)
        {
            duk_get_prop_index(ctx, stackIndex, i);
            if (duk_is_string(ctx, -1))
                ret.Push(String(duk_get_string(ctx, -1)));
            duk_pop(ctx);
        }
    }

    return ret;
}
Exemplo n.º 17
0
static gboolean
gum_append_match (GumAddress address,
                  gsize size,
                  GumDukCore * core)
{
  GumDukScope scope = GUM_DUK_SCOPE_INIT (core);
  duk_context * ctx = scope.ctx;

  duk_push_object (ctx);

  _gum_duk_push_uint64 (ctx, address, core);
  duk_put_prop_string (ctx, -2, "address");

  duk_push_uint (ctx, size);
  duk_put_prop_string (ctx, -2, "size");

  duk_put_prop_index (ctx, -2, (duk_uarridx_t) duk_get_length (ctx, -2));

  return TRUE;
}
Exemplo n.º 18
0
/*
 * like luaL_ref, but assumes storage in "refs" property of heap stash
 */
int
mn_ref(duk_context *ctx) {
	int ref;
	if (duk_is_undefined(ctx, -1)) {
		duk_pop(ctx);
		return 0;
	}
	/* Get the "refs" array in the heap stash */
	duk_push_heap_stash(ctx);
	duk_get_prop_string(ctx, -1, "refs");
	duk_remove(ctx, -2);

	/* ref = refs[0] */
	duk_get_prop_index(ctx, -1, 0);
	ref = duk_get_int(ctx, -1);
	duk_pop(ctx);

	/* If there was a free slot, remove it from the list */
	if (ref != 0) {
		/* refs[0] = refs[ref] */
		duk_get_prop_index(ctx, -1, ref);
		duk_put_prop_index(ctx, -2, 0);
	} else {
		/* Otherwise use the end of the list */
		ref = duk_get_length(ctx, -1);
	}

	/* Swap the array and the user value in the stack */
	duk_insert(ctx, -2);

	/* refs[ref] = value */
	duk_put_prop_index(ctx, -2, ref);

	/* Remove the refs array from the stack. */
	duk_pop(ctx);

	return ref;
}
Exemplo n.º 19
0
void GCObjectPool::addNewList() {
    Isolate *isolate = Isolate::GetCurrent();
    duk_context *ctx = isolate->GetDukContext();

    // Get the "refs" array in the heap stash
    duk_push_global_stash(ctx);
    duk_get_prop_string(ctx, -1, "__object_list");
    duk_remove(ctx, -2);

    int type = duk_get_type(ctx, -1);

    int freeSlot;

    // freeSlot = scopeList[0]
    duk_get_prop_index(ctx, -1, 0);                                // <scopeList> <scopeList[0]>
    freeSlot = duk_get_int(ctx, -1);
    duk_pop(ctx);                                                  // <scopeList>

    if (freeSlot != 0) {
        // scopeList[0] = scopeList[freeSlot]
        duk_get_prop_index(ctx, -1, (duk_uarridx_t) freeSlot);    // <scopeList> <scopeList[freeSlot]>
        duk_put_prop_index(ctx, -2, 0);                            // <scopeList>
    } else {
        // freeSlot = scopeList.length;
        freeSlot = (int) duk_get_length(ctx, -1);
    }

    duk_push_array(ctx);
    list_ptr_ = duk_get_heapptr(ctx, -1);                         // <scopeList> <scope>

    // scopeList[freeSlot] = scope
    duk_put_prop_index(ctx, -2, (duk_uarridx_t) freeSlot);        // <scopeList>

    // Remove the refs array from the stack.
    duk_pop(ctx);                                                  //

    list_idx_ = freeSlot;
}
Exemplo n.º 20
0
JavaScriptObject::~JavaScriptObject() {
    if (!m_instance) {
        // Instance has already been cleaned up.
        return;
    }
    // The instance still exists - detach from it.
    duk_push_global_object(m_context);
    duk_push_heapptr(m_context, m_instance);

    // Remove this pointer from the JS object's property.
    if (duk_get_prop_string(m_context, -1, WRAPPER_THIS_PROP_NAME)) {
        const duk_size_t length = duk_get_length(m_context, -1);
        for (duk_uarridx_t i = 0; i < length; ++i) {
            duk_get_prop_index(m_context, -1, i);

            const void* ptr = duk_get_pointer(m_context, -1);
            duk_pop(m_context);

            if (this == ptr) {
                // Remove this object from the array.
                duk_del_prop_index(m_context, -1, i);
                break;
            }
        }
    }

    // Pop the array (or undefined if there was none).
    duk_pop(m_context);

    if (m_nextFinalizer) {
        // Reset to the object's previous finalizer.
        duk_push_c_function(m_context, m_nextFinalizer, 1);
        duk_set_finalizer(m_context, -2);
    }

    // Pop the instance & global object.
    duk_pop_2(m_context);
}
Exemplo n.º 21
0
int GlobalStash::AddObject(void *ptr) {
    Isolate *isolate = Isolate::GetCurrent();
    duk_context *ctx = isolate->GetDukContext();

    // Get the "refs" array in the heap stash
    duk_push_global_stash(ctx);
    duk_get_prop_string(ctx, -1, name_);
    duk_remove(ctx, -2);

    int type = duk_get_type(ctx, -1);

    int freeSlot;

    // freeSlot = scopeList[0]
    duk_get_prop_index(ctx, -1, 0);                                // <scopeList> <scopeList[0]>
    freeSlot = duk_get_int(ctx, -1);
    duk_pop(ctx);                                                  // <scopeList>

    if (freeSlot != 0) {
        // scopeList[0] = scopeList[freeSlot]
        duk_get_prop_index(ctx, -1, (duk_uarridx_t) freeSlot);    // <scopeList> <scopeList[freeSlot]>
        duk_put_prop_index(ctx, -2, 0);                            // <scopeList>
    } else {
        // freeSlot = scopeList.length;
        freeSlot = (int) duk_get_length(ctx, -1);
    }

    duk_push_heapptr(ctx, ptr);                                   // <scopeList> <scope>

    // scopeList[freeSlot] = scope
    duk_put_prop_index(ctx, -2, (duk_uarridx_t) freeSlot);        // <scopeList>

    // Remove the refs array from the stack.
    duk_pop(ctx);                                                  //

    return freeSlot;
}
Exemplo n.º 22
0
static int duk_assemble(RAsm *a, RAsmOp *op, const char *str) {
	int i, res = 0;
	// call myasm function if available
	duk_push_global_stash (ctx);
	duk_dup (ctx, 0);  /* timer callback */
	duk_get_prop_string (ctx, -2, "asmfun");
	a->cur->user = duk_require_tval (ctx, -1);
	if (duk_is_callable(ctx, -1)) {
		duk_push_string (ctx, str);
		duk_call (ctx, 1);
		// [ array of bytes ]
		//duk_dup_top (ctx);
		res = duk_get_length (ctx, -1);
		op->size = res;
		for (i=0; i<res; i++) {
			duk_dup_top (ctx);
			duk_get_prop_index (ctx, -2, i);
			op->buf[i] = duk_to_int (ctx, -1);
		}
	}
	if (res<1)
		res = -1;
	return res;
}
Exemplo n.º 23
0
//-----------------------------------------------------------------------------
void AdTiledManager::Load(const char* pName) {
	Unload();

	char pFN[FILENAME_MAX];
	sprintf(pFN, MAP_LOCATION, pName);

	duk_context* ctx = s_pJSCtx;

	duk_push_string_file(ctx, pFN);
	duk_json_decode(ctx, -1);

	if(!duk_is_object(ctx, -1)) {
		fprintf(stderr, "NOTE: Failed parse %s.json!\n", pName);
		return;
	}
	
	duk_get_prop_string(ctx, -1, "width");
	m_iWidth = duk_to_int(ctx, -1);
	duk_pop(ctx);

	duk_get_prop_string(ctx, -1, "height");
	m_iHeight = duk_to_int(ctx, -1);
	duk_pop(ctx);

	duk_get_prop_string(ctx, -1, "layers");
	
	if(duk_is_array(ctx, -1)) {
		m_nLayers  = duk_get_length(ctx, -1);
		m_pIndices = (int**) calloc(m_nLayers, sizeof(int*));

		for(int j=0; j<m_nLayers; ++j) {
			duk_get_prop_index(ctx, -1, j);

			// NOTE: if this is a tile layer grab the indices, otherwise set
			// to NULL
			duk_get_prop_string(ctx, -1, "data");

			if(duk_is_array(ctx, -1)) {
				int size = duk_get_length(ctx, -1);

				if((m_iWidth*m_iHeight) == size) {
					m_pIndices[j] = (int*) malloc(size*sizeof(int));

					for(int i=0; i<size; ++i) {
						duk_get_prop_index(ctx, -1, i);
						m_pIndices[j][i] = duk_to_int(ctx, -1);
						duk_pop(ctx);
					}
				}
			}

			duk_pop(ctx);

			// NOTE: loop over the map entities and add them to the array of
			// entities
			duk_get_prop_string(ctx, -1, "name");

			if(duk_is_string(ctx, -1)) {
				if(!strcmp(duk_get_string(ctx, -1), "entities")) {
					// NOTE: -2 referring back to object and not the string
					duk_get_prop_string(ctx, -2, "objects");

					if(duk_is_array(ctx, -1)) {
						int size = duk_get_length(ctx, -1);
						
						for(int e=0; e<size; ++e) {
							duk_get_prop_index(ctx, -1, e);

							duk_get_prop_string(ctx, -1, "type");
							const char* type = duk_get_string(ctx, -1);

							AdEntity* pEnt = NULL;

							if(!strcmp(type, "NPC-PLAYER")) {
								duk_pop(ctx);
								pEnt = new AdPlayer();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-TEST")) {
								duk_pop(ctx);
								pEnt = new AdMoveable();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "TEST")) {
								duk_pop(ctx);
								pEnt = new AdEntity();
								pEnt->Load(ctx);
							} else {
								duk_pop(ctx);
							}

							if(pEnt) {
								m_pEntities = (AdEntity**) realloc(
									m_pEntities, ++m_nEntities*sizeof(AdEntity*)
								); m_pEntities[m_nEntities-1] = pEnt;
							}

							duk_pop(ctx);
						}
					}

					duk_pop(ctx);
				}
			}

			duk_pop_2(ctx);
		}
	}

	duk_pop_2(ctx);
}
Exemplo n.º 24
0
static duk_ret_t test_func(duk_context *ctx, void *udata) {
	(void) udata;

	if (ctx) {
		printf("dummy - return here\n"); fflush(stdout);
		return 0;
	}

	/* Up-to-date for Duktape 1.3.0, alphabetical order:
	 * $ cd website/api; ls *.yaml
	 */

	(void) duk_alloc_raw(ctx, 0);
	(void) duk_alloc(ctx, 0);
	(void) duk_base64_decode(ctx, 0);
	(void) duk_base64_encode(ctx, 0);
	(void) duk_buffer_to_string(ctx, 0);
	(void) duk_call_method(ctx, 0);
	(void) duk_call_prop(ctx, 0, 0);
	(void) duk_call(ctx, 0);
	(void) duk_char_code_at(ctx, 0, 0);
	(void) duk_check_stack_top(ctx, 0);
	(void) duk_check_stack(ctx, 0);
	(void) duk_check_type_mask(ctx, 0, 0);
	(void) duk_check_type(ctx, 0, 0);
	(void) duk_compact(ctx, 0);
	(void) duk_compile_lstring_filename(ctx, 0, "dummy", 0);
	(void) duk_compile_lstring(ctx, 0, "dummy", 0);
	(void) duk_compile_string_filename(ctx, 0, "dummy");
	(void) duk_compile_string(ctx, 0, "dummy");
	(void) duk_compile(ctx, 0);
	(void) duk_concat(ctx, 0);
	(void) duk_config_buffer(ctx, 0, NULL, 0);
	(void) duk_copy(ctx, 0, 0);
	(void) duk_create_heap_default();
	(void) duk_create_heap(NULL, NULL, NULL, NULL, NULL);
	(void) duk_debugger_attach(ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	(void) duk_debugger_cooperate(ctx);
	(void) duk_debugger_detach(ctx);
	(void) duk_debugger_notify(ctx, 0);
	(void) duk_debugger_pause(ctx);
	(void) duk_decode_string(ctx, 0, NULL, NULL);
	(void) duk_def_prop(ctx, 0, 0);
	(void) duk_del_prop_index(ctx, 0, 0);
	(void) duk_del_prop_string(ctx, 0, "dummy");
	(void) duk_del_prop(ctx, 0);
	(void) duk_destroy_heap(ctx);
	(void) duk_dump_function(ctx);
	(void) duk_dup_top(ctx);
	(void) duk_dup(ctx, 0);
	(void) duk_enum(ctx, 0, 0);
	(void) duk_equals(ctx, 0, 0);
	duk_error_va(ctx, 0, NULL, NULL);
	duk_error(ctx, 0, "dummy");  /* (void) cast won't work without variadic macros */
	(void) duk_eval_lstring_noresult(ctx, "dummy", 0);
	(void) duk_eval_lstring(ctx, "dummy", 0);
	(void) duk_eval_noresult(ctx);
	(void) duk_eval_string_noresult(ctx, "dummy");
	(void) duk_eval_string(ctx, "dummy");
	(void) duk_eval(ctx);
	(void) duk_fatal(ctx, "dummy");
	(void) duk_free_raw(ctx, NULL);
	(void) duk_free(ctx, NULL);
	(void) duk_gc(ctx, 0);
	(void) duk_get_boolean(ctx, 0);
	(void) duk_get_buffer_data(ctx, 0, NULL);
	(void) duk_get_buffer(ctx, 0, NULL);
	(void) duk_get_c_function(ctx, 0);
	(void) duk_get_context(ctx, 0);
	(void) duk_get_current_magic(ctx);
	(void) duk_get_error_code(ctx, 0);
	(void) duk_get_finalizer(ctx, 0);
	(void) duk_get_global_string(ctx, 0);
	(void) duk_get_heapptr(ctx, 0);
	(void) duk_get_int(ctx, 0);
	(void) duk_get_length(ctx, 0);
	(void) duk_get_lstring(ctx, 0, NULL);
	(void) duk_get_magic(ctx, 0);
	(void) duk_get_memory_functions(ctx, NULL);
	(void) duk_get_number(ctx, 0);
	(void) duk_get_pointer(ctx, 0);
	(void) duk_get_prop_index(ctx, 0, 0);
	(void) duk_get_prop_string(ctx, 0, "dummy");
	(void) duk_get_prop(ctx, 0);
	(void) duk_get_prototype(ctx, 0);
	(void) duk_get_string(ctx, 0);
	(void) duk_get_top_index(ctx);
	(void) duk_get_top(ctx);
	(void) duk_get_type_mask(ctx, 0);
	(void) duk_get_type(ctx, 0);
	(void) duk_get_uint(ctx, 0);
	(void) duk_has_prop_index(ctx, 0, 0);
	(void) duk_has_prop_string(ctx, 0, "dummy");
	(void) duk_has_prop(ctx, 0);
	(void) duk_hex_decode(ctx, 0);
	(void) duk_hex_encode(ctx, 0);
	(void) duk_insert(ctx, 0);
	(void) duk_instanceof(ctx, 0, 0);
	(void) duk_is_array(ctx, 0);
	(void) duk_is_boolean(ctx, 0);
	(void) duk_is_bound_function(ctx, 0);
	(void) duk_is_buffer(ctx, 0);
	(void) duk_is_callable(ctx, 0);
	(void) duk_is_c_function(ctx, 0);
	(void) duk_is_constructor_call(ctx);
	(void) duk_is_dynamic_buffer(ctx, 0);
	(void) duk_is_ecmascript_function(ctx, 0);
	(void) duk_is_error(ctx, 0);
	(void) duk_is_eval_error(ctx, 0);
	(void) duk_is_fixed_buffer(ctx, 0);
	(void) duk_is_function(ctx, 0);
	(void) duk_is_lightfunc(ctx, 0);
	(void) duk_is_nan(ctx, 0);
	(void) duk_is_null_or_undefined(ctx, 0);
	(void) duk_is_null(ctx, 0);
	(void) duk_is_number(ctx, 0);
	(void) duk_is_object_coercible(ctx, 0);
	(void) duk_is_object(ctx, 0);
	(void) duk_is_pointer(ctx, 0);
	(void) duk_is_primitive(ctx, 0);
	(void) duk_is_range_error(ctx, 0);
	(void) duk_is_reference_error(ctx, 0);
	(void) duk_is_strict_call(ctx);
	(void) duk_is_string(ctx, 0);
	(void) duk_is_syntax_error(ctx, 0);
	(void) duk_is_thread(ctx, 0);
	(void) duk_is_type_error(ctx, 0);
	(void) duk_is_undefined(ctx, 0);
	(void) duk_is_uri_error(ctx, 0);
	(void) duk_is_valid_index(ctx, 0);
	(void) duk_join(ctx, 0);
	(void) duk_json_decode(ctx, 0);
	(void) duk_json_encode(ctx, 0);
	(void) duk_load_function(ctx);
	(void) duk_map_string(ctx, 0, NULL, NULL);
	(void) duk_new(ctx, 0);
	(void) duk_next(ctx, 0, 0);
	(void) duk_normalize_index(ctx, 0);
	(void) duk_pcall_method(ctx, 0);
	(void) duk_pcall_prop(ctx, 0, 0);
	(void) duk_pcall(ctx, 0);
	(void) duk_pcompile_lstring_filename(ctx, 0, "dummy", 0);
	(void) duk_pcompile_lstring(ctx, 0, "dummy", 0);
	(void) duk_pcompile_string_filename(ctx, 0, "dummy");
	(void) duk_pcompile_string(ctx, 0, "dummy");
	(void) duk_pcompile(ctx, 0);
	(void) duk_peval_lstring_noresult(ctx, "dummy", 0);
	(void) duk_peval_lstring(ctx, "dummy", 0);
	(void) duk_peval_noresult(ctx);
	(void) duk_peval_string_noresult(ctx, "dummy");
	(void) duk_peval_string(ctx, "dummy");
	(void) duk_peval(ctx);
	(void) duk_pnew(ctx, 0);
	(void) duk_pop_2(ctx);
	(void) duk_pop_3(ctx);
	(void) duk_pop_n(ctx, 0);
	(void) duk_pop(ctx);
	(void) duk_push_array(ctx);
	(void) duk_push_boolean(ctx, 0);
	(void) duk_push_buffer_object(ctx, 0, 0, 0, 0);
	(void) duk_push_buffer(ctx, 0, 0);
	(void) duk_push_c_function(ctx, NULL, 0);
	(void) duk_push_c_lightfunc(ctx, NULL, 0, 0, 0);
	(void) duk_push_context_dump(ctx);
	(void) duk_push_current_function(ctx);
	(void) duk_push_current_thread(ctx);
	(void) duk_push_dynamic_buffer(ctx, 0);
	(void) duk_push_error_object_va(ctx, 0, NULL, NULL);
	(void) duk_push_error_object(ctx, 0, "dummy");
	(void) duk_push_external_buffer(ctx);
	(void) duk_push_false(ctx);
	(void) duk_push_fixed_buffer(ctx, 0);
	(void) duk_push_global_object(ctx);
	(void) duk_push_global_stash(ctx);
	(void) duk_push_heap_stash(ctx);
	(void) duk_push_heapptr(ctx, NULL);
	(void) duk_push_int(ctx, 0);
	(void) duk_push_lstring(ctx, "dummy", 0);
	(void) duk_push_nan(ctx);
	(void) duk_push_null(ctx);
	(void) duk_push_number(ctx, 0.0);
	(void) duk_push_object(ctx);
	(void) duk_push_pointer(ctx, NULL);
	(void) duk_push_sprintf(ctx, "dummy");
	(void) duk_push_string(ctx, "dummy");
	(void) duk_push_this(ctx);
	(void) duk_push_thread_new_globalenv(ctx);
	(void) duk_push_thread_stash(ctx, NULL);
	(void) duk_push_thread(ctx);
	(void) duk_push_true(ctx);
	(void) duk_push_uint(ctx, 0);
	(void) duk_push_undefined(ctx);
	(void) duk_push_vsprintf(ctx, "dummy", NULL);
	(void) duk_put_function_list(ctx, 0, NULL);
	(void) duk_put_global_string(ctx, NULL);
	(void) duk_put_number_list(ctx, 0, NULL);
	(void) duk_put_prop_index(ctx, 0, 0);
	(void) duk_put_prop_string(ctx, 0, "dummy");
	(void) duk_put_prop(ctx, 0);
	(void) duk_realloc_raw(ctx, NULL, 0);
	(void) duk_realloc(ctx, NULL, 0);
	(void) duk_remove(ctx, 0);
	(void) duk_replace(ctx, 0);
	(void) duk_require_boolean(ctx, 0);
	(void) duk_require_buffer_data(ctx, 0, NULL);
	(void) duk_require_buffer(ctx, 0, NULL);
	(void) duk_require_c_function(ctx, 0);
	(void) duk_require_callable(ctx, 0);
	(void) duk_require_context(ctx, 0);
	(void) duk_require_function(ctx, 0);
	(void) duk_require_heapptr(ctx, 0);
	(void) duk_require_int(ctx, 0);
	(void) duk_require_lstring(ctx, 0, NULL);
	(void) duk_require_normalize_index(ctx, 0);
	(void) duk_require_null(ctx, 0);
	(void) duk_require_number(ctx, 0);
	(void) duk_require_object_coercible(ctx, 0);
	(void) duk_require_pointer(ctx, 0);
	(void) duk_require_stack_top(ctx, 0);
	(void) duk_require_stack(ctx, 0);
	(void) duk_require_string(ctx, 0);
	(void) duk_require_top_index(ctx);
	(void) duk_require_type_mask(ctx, 0, 0);
	(void) duk_require_uint(ctx, 0);
	(void) duk_require_undefined(ctx, 0);
	(void) duk_require_valid_index(ctx, 0);
	(void) duk_resize_buffer(ctx, 0, 0);
	(void) duk_safe_call(ctx, NULL, NULL, 0, 0);
	(void) duk_safe_to_lstring(ctx, 0, NULL);
	(void) duk_safe_to_string(ctx, 0);
	(void) duk_set_finalizer(ctx, 0);
	(void) duk_set_global_object(ctx);
	(void) duk_set_magic(ctx, 0, 0);
	(void) duk_set_prototype(ctx, 0);
	(void) duk_set_top(ctx, 0);
	(void) duk_steal_buffer(ctx, 0, NULL);
	(void) duk_strict_equals(ctx, 0, 0);
	(void) duk_substring(ctx, 0, 0, 0);
	(void) duk_swap_top(ctx, 0);
	(void) duk_swap(ctx, 0, 0);
	(void) duk_throw(ctx);
	(void) duk_to_boolean(ctx, 0);
	(void) duk_to_buffer(ctx, 0, NULL);
	(void) duk_to_defaultvalue(ctx, 0, 0);
	(void) duk_to_dynamic_buffer(ctx, 0, NULL);
	(void) duk_to_fixed_buffer(ctx, 0, NULL);
	(void) duk_to_int32(ctx, 0);
	(void) duk_to_int(ctx, 0);
	(void) duk_to_lstring(ctx, 0, NULL);
	(void) duk_to_null(ctx, 0);
	(void) duk_to_number(ctx, 0);
	(void) duk_to_object(ctx, 0);
	(void) duk_to_pointer(ctx, 0);
	(void) duk_to_primitive(ctx, 0, 0);
	(void) duk_to_string(ctx, 0);
	(void) duk_to_uint16(ctx, 0);
	(void) duk_to_uint32(ctx, 0);
	(void) duk_to_uint(ctx, 0);
	(void) duk_to_undefined(ctx, 0);
	(void) duk_trim(ctx, 0);
	(void) duk_xcopy_top(ctx, NULL, 0);
	(void) duk_xmove_top(ctx, NULL, 0);

	printf("never here\n"); fflush(stdout);
	return 0;
}
Exemplo n.º 25
0
void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hobject *enum_target;
	duk_hobject *curr;
	duk_hobject *res;
#if defined(DUK_USE_ES6_PROXY)
	duk_hobject *h_proxy_target;
	duk_hobject *h_proxy_handler;
	duk_hobject *h_trap_result;
#endif
	duk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */

	DUK_ASSERT(ctx != NULL);

	DUK_DDD(DUK_DDDPRINT("create enumerator, stack top: %ld", (long) duk_get_top(ctx)));

	enum_target = duk_require_hobject(ctx, -1);
	DUK_ASSERT(enum_target != NULL);

	duk_push_object_internal(ctx);
	res = duk_require_hobject(ctx, -1);

	DUK_DDD(DUK_DDDPRINT("created internal object"));

	/* [enum_target res] */

	/* Target must be stored so that we can recheck whether or not
	 * keys still exist when we enumerate.  This is not done if the
	 * enumeration result comes from a proxy trap as there is no
	 * real object to check against.
	 */
	duk_push_hobject(ctx, enum_target);
	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET);

	/* Initialize index so that we skip internal control keys. */
	duk_push_int(ctx, DUK__ENUM_START_INDEX);
	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_INT_NEXT);

	/*
	 *  Proxy object handling
	 */

#if defined(DUK_USE_ES6_PROXY)
	if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
		goto skip_proxy;
	}
	if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
	                                        enum_target,
	                                        &h_proxy_target,
	                                        &h_proxy_handler))) {
		goto skip_proxy;
	}

	DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
	duk_push_hobject(ctx, h_proxy_handler);
	if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_ENUMERATE)) {
		/* No need to replace the 'enum_target' value in stack, only the
		 * enum_target reference.  This also ensures that the original
		 * enum target is reachable, which keeps the proxy and the proxy
		 * target reachable.  We do need to replace the internal _target.
		 */
		DUK_DDD(DUK_DDDPRINT("no enumerate trap, enumerate proxy target instead"));
		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
		enum_target = h_proxy_target;

		duk_push_hobject(ctx, enum_target);  /* -> [ ... enum_target res handler undefined target ] */
		duk_put_prop_stridx(ctx, -4, DUK_STRIDX_INT_TARGET);

		duk_pop_2(ctx);  /* -> [ ... enum_target res ] */
		goto skip_proxy;
	}

	/* [ ... enum_target res handler trap ] */
	duk_insert(ctx, -2);
	duk_push_hobject(ctx, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */
	duk_call_method(ctx, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */
	h_trap_result = duk_require_hobject(ctx, -1);
	DUK_UNREF(h_trap_result);

	/* Copy trap result keys into the enumerator object. */
	len = (duk_uint_fast32_t) duk_get_length(ctx, -1);
	for (i = 0; i < len; i++) {
		/* XXX: not sure what the correct semantic details are here,
		 * e.g. handling of missing values (gaps), handling of non-array
		 * trap results, etc.
		 *
		 * For keys, we simply skip non-string keys which seems to be
		 * consistent with how e.g. Object.keys() will process proxy trap
		 * results (ES6 draft, Section 19.1.2.14).
		 */
		if (duk_get_prop_index(ctx, -1, i) && duk_is_string(ctx, -1)) {
			/* [ ... enum_target res trap_result val ] */
			duk_push_true(ctx);
			/* [ ... enum_target res trap_result val true ] */
			duk_put_prop(ctx, -4);
		} else {
			duk_pop(ctx);
		}
	}
	/* [ ... enum_target res trap_result ] */
	duk_pop(ctx);
	duk_remove(ctx, -2);

	/* [ ... res ] */

	/* The internal _target property is kept pointing to the original
	 * enumeration target (the proxy object), so that the enumerator
	 * 'next' operation can read property values if so requested.  The
	 * fact that the _target is a proxy disables key existence check
	 * during enumeration.
	 */
	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
	goto compact_and_return;

 skip_proxy:
#endif  /* DUK_USE_ES6_PROXY */

	curr = enum_target;
	while (curr) {
		/*
		 *  Virtual properties.
		 *
		 *  String and buffer indices are virtual and always enumerable,
		 *  'length' is virtual and non-enumerable.  Array and arguments
		 *  object props have special behavior but are concrete.
		 */

		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) ||
		    DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(curr)) {
			/* String and buffer enumeration behavior is identical now,
			 * so use shared handler.
			 */
			if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
				duk_hstring *h_val;
				h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
			} else {
				duk_hbuffer *h_val;
				DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(curr));
				h_val = duk_hobject_get_internal_value_buffer(thr->heap, curr);
				DUK_ASSERT(h_val != NULL);  /* buffer objects must not created without internal value */
				len = (duk_uint_fast32_t) DUK_HBUFFER_GET_SIZE(h_val);
			}

			for (i = 0; i < len; i++) {
				duk_hstring *k;

				k = duk_heap_string_intern_u32_checked(thr, i);
				DUK_ASSERT(k);
				duk_push_hstring(ctx, k);
				duk_push_true(ctx);

				/* [enum_target res key true] */
				duk_put_prop(ctx, -3);

				/* [enum_target res] */
			}

			/* 'length' property is not enumerable, but is included if
			 * non-enumerable properties are requested.
			 */

			if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
				duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
				duk_push_true(ctx);
				duk_put_prop(ctx, -3);
			}
		} else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(curr)) {
			if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
				duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
				duk_push_true(ctx);
				duk_put_prop(ctx, -3);
			}
		}

		/*
		 *  Array part
		 *
		 *  Note: ordering between array and entry part must match 'abandon array'
		 *  behavior in duk_hobject_props.c: key order after an array is abandoned
		 *  must be the same.
		 */

		for (i = 0; i < (duk_uint_fast32_t) curr->a_size; i++) {
			duk_hstring *k;
			duk_tval *tv;

			tv = DUK_HOBJECT_A_GET_VALUE_PTR(curr, i);
			if (DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
				continue;
			}
			k = duk_heap_string_intern_u32_checked(thr, i);
			DUK_ASSERT(k);

			duk_push_hstring(ctx, k);
			duk_push_true(ctx);

			/* [enum_target res key true] */
			duk_put_prop(ctx, -3);

			/* [enum_target res] */
		}

		/*
		 *  Entries part
		 */

		for (i = 0; i < (duk_uint_fast32_t) curr->e_next; i++) {
			duk_hstring *k;

			k = DUK_HOBJECT_E_GET_KEY(curr, i);
			if (!k) {
				continue;
			}
			if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(curr, i) &&
			    !(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
				continue;
			}
			if (DUK_HSTRING_HAS_INTERNAL(k) &&
			    !(enum_flags & DUK_ENUM_INCLUDE_INTERNAL)) {
				continue;
			}
			if ((enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) &&
			    (DUK_HSTRING_GET_ARRIDX_SLOW(k) == DUK_HSTRING_NO_ARRAY_INDEX)) {
				continue;
			}

			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(curr, i) ||
			           !DUK_TVAL_IS_UNDEFINED_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(curr, i)->v));

			duk_push_hstring(ctx, k);
			duk_push_true(ctx);

			/* [enum_target res key true] */
			duk_put_prop(ctx, -3);

			/* [enum_target res] */
		}

		if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
			break;
		}

		curr = curr->prototype;
	}

	/* [enum_target res] */

	duk_remove(ctx, -2);

	/* [res] */

	if ((enum_flags & (DUK_ENUM_ARRAY_INDICES_ONLY | DUK_ENUM_SORT_ARRAY_INDICES)) ==
	                  (DUK_ENUM_ARRAY_INDICES_ONLY | DUK_ENUM_SORT_ARRAY_INDICES)) {
		/*
		 *  Some E5/E5.1 algorithms require that array indices are iterated
		 *  in a strictly ascending order.  This is the case for e.g.
		 *  Array.prototype.forEach() and JSON.stringify() PropertyList
		 *  handling.
		 *
		 *  To ensure this property for arrays with an array part (and
		 *  arbitrary objects too, since e.g. forEach() can be applied
		 *  to an array), the caller can request that we sort the keys
		 *  here.
		 */

		/* XXX: avoid this at least when enum_target is an Array, it has an
		 * array part, and no ancestor properties were included?  Not worth
		 * it for JSON, but maybe worth it for forEach().
		 */

		/* XXX: may need a 'length' filter for forEach()
		 */
		DUK_DDD(DUK_DDDPRINT("sort array indices by caller request"));
		duk__sort_array_indices(res);
	}

#if defined(DUK_USE_ES6_PROXY)
 compact_and_return:
#endif
	/* compact; no need to seal because object is internal */
	duk_hobject_compact_props(thr, res);

	DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
}
Exemplo n.º 26
0
/* Shared helper for Object.getOwnPropertyNames() and Object.keys().
 * Magic: 0=getOwnPropertyNames, 1=Object.keys.
 */
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hobject *obj;
#if defined(DUK_USE_ES6_PROXY)
	duk_hobject *h_proxy_target;
	duk_hobject *h_proxy_handler;
	duk_hobject *h_trap_result;
	duk_uarridx_t i, len, idx;
#endif
	duk_small_uint_t enum_flags;

	DUK_ASSERT_TOP(ctx, 1);

	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
	DUK_ASSERT(obj != NULL);
	DUK_UNREF(obj);

#if defined(DUK_USE_ES6_PROXY)
	if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
	                                        obj,
	                                        &h_proxy_target,
	                                        &h_proxy_handler))) {
		goto skip_proxy;
	}

	duk_push_hobject(ctx, h_proxy_handler);
	if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_OWN_KEYS)) {
		/* Careful with reachability here: don't pop 'obj' before pushing
		 * proxy target.
		 */
		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
		duk_pop_2(ctx);
		duk_push_hobject(ctx, h_proxy_target);
		duk_replace(ctx, 0);
		DUK_ASSERT_TOP(ctx, 1);
		goto skip_proxy;
	}

	/* [ obj handler trap ] */
	duk_insert(ctx, -2);
	duk_push_hobject(ctx, h_proxy_target);  /* -> [ obj trap handler target ] */
	duk_call_method(ctx, 1 /*nargs*/);      /* -> [ obj trap_result ] */
	h_trap_result = duk_require_hobject(ctx, -1);
	DUK_UNREF(h_trap_result);

	len = (duk_uarridx_t) duk_get_length(ctx, -1);
	idx = 0;
	duk_push_array(ctx);
	for (i = 0; i < len; i++) {
		/* [ obj trap_result res_arr ] */
		if (duk_get_prop_index(ctx, -2, i) && duk_is_string(ctx, -1)) {
			/* XXX: for Object.keys() we should check enumerability of key */
			/* [ obj trap_result res_arr propname ] */
			duk_put_prop_index(ctx, -2, idx);
			idx++;
		} else {
			duk_pop(ctx);
		}
	}

	/* XXX: for Object.keys() the [[OwnPropertyKeys]] result (trap result)
	 * should be filtered so that only enumerable keys remain.  Enumerability
	 * should be checked with [[GetOwnProperty]] on the original object
	 * (i.e., the proxy in this case).  If the proxy has a getOwnPropertyDescriptor
	 * trap, it should be triggered for every property.  If the proxy doesn't have
	 * the trap, enumerability should be checked against the target object instead.
	 * We don't do any of this now, so Object.keys() and Object.getOwnPropertyNames()
	 * return the same result now for proxy traps.  We still do clean up the trap
	 * result, so that Object.keys() and Object.getOwnPropertyNames() will return a
	 * clean array of strings without gaps.
	 */
	return 1;

 skip_proxy:
#endif  /* DUK_USE_ES6_PROXY */

	DUK_ASSERT_TOP(ctx, 1);

	if (duk_get_current_magic(ctx)) {
		/* Object.keys */
		enum_flags = DUK_ENUM_OWN_PROPERTIES_ONLY |
		             DUK_ENUM_NO_PROXY_BEHAVIOR;
	} else {
		/* Object.getOwnPropertyNames */
		enum_flags = DUK_ENUM_INCLUDE_NONENUMERABLE |
		             DUK_ENUM_OWN_PROPERTIES_ONLY |
		             DUK_ENUM_NO_PROXY_BEHAVIOR;
	}

	return duk_hobject_get_enumerated_keys(ctx, enum_flags);
}
Exemplo n.º 27
0
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hstring *h_input;
	duk_hstring *h_match;
	duk_hstring *h_search;
	duk_hobject *h_re;
	duk_bufwriter_ctx bw_alloc;
	duk_bufwriter_ctx *bw;
#ifdef DUK_USE_REGEXP_SUPPORT
	duk_bool_t is_regexp;
	duk_bool_t is_global;
#endif
	duk_bool_t is_repl_func;
	duk_uint32_t match_start_coff, match_start_boff;
#ifdef DUK_USE_REGEXP_SUPPORT
	duk_int_t match_caps;
#endif
	duk_uint32_t prev_match_end_boff;
	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
	duk_size_t tmp_sz;

	DUK_ASSERT_TOP(ctx, 2);
	h_input = duk_push_this_coercible_to_string(ctx);
	DUK_ASSERT(h_input != NULL);

	bw = &bw_alloc;
	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */

	DUK_ASSERT_TOP(ctx, 4);

	/* stack[0] = search value
	 * stack[1] = replace value
	 * stack[2] = input string
	 * stack[3] = result buffer
	 */

	h_re = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP);
	if (h_re) {
#ifdef DUK_USE_REGEXP_SUPPORT
		is_regexp = 1;
		is_global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);

		if (is_global) {
			/* start match from beginning */
			duk_push_int(ctx, 0);
			duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
		}
#else  /* DUK_USE_REGEXP_SUPPORT */
		return DUK_RET_UNSUPPORTED_ERROR;
#endif  /* DUK_USE_REGEXP_SUPPORT */
	} else {
		duk_to_string(ctx, 0);
#ifdef DUK_USE_REGEXP_SUPPORT
		is_regexp = 0;
		is_global = 0;
#endif
	}

	if (duk_is_function(ctx, 1)) {
		is_repl_func = 1;
		r_start = NULL;
		r_end = NULL;
	} else {
		duk_hstring *h_repl;

		is_repl_func = 0;
		h_repl = duk_to_hstring(ctx, 1);
		DUK_ASSERT(h_repl != NULL);
		r_start = DUK_HSTRING_GET_DATA(h_repl);
		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
	}

	prev_match_end_boff = 0;

	for (;;) {
		/*
		 *  If matching with a regexp:
		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
		 *      on a non-match
		 *    - global RegExp: on match, lastIndex will be updated by regexp
		 *      executor to point to next char after the matching part (so that
		 *      characters in the matching part are not matched again)
		 *
		 *  If matching with a string:
		 *    - always non-global match, find first occurrence
		 *
		 *  We need:
		 *    - The character offset of start-of-match for the replacer function
		 *    - The byte offsets for start-of-match and end-of-match to implement
		 *      the replacement values $&, $`, and $', and to copy non-matching
		 *      input string portions (including header and trailer) verbatim.
		 *
		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
		 *  behave in the replacement process; e.g. is matching done first for
		 *  all matches (in the global RegExp case) before any replacer calls
		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
		 */

		DUK_ASSERT_TOP(ctx, 4);

#ifdef DUK_USE_REGEXP_SUPPORT
		if (is_regexp) {
			duk_dup(ctx, 0);
			duk_dup(ctx, 2);
			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
			if (!duk_is_object(ctx, -1)) {
				duk_pop(ctx);
				break;
			}

			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
			DUK_ASSERT(duk_is_number(ctx, -1));
			match_start_coff = duk_get_int(ctx, -1);
			duk_pop(ctx);

			duk_get_prop_index(ctx, -1, 0);
			DUK_ASSERT(duk_is_string(ctx, -1));
			h_match = duk_get_hstring(ctx, -1);
			DUK_ASSERT(h_match != NULL);
			duk_pop(ctx);  /* h_match is borrowed, remains reachable through match_obj */

			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
				/* This should be equivalent to match() algorithm step 8.f.iii.2:
				 * detect an empty match and allow it, but don't allow it twice.
				 */
				duk_uint32_t last_index;

				duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
				last_index = (duk_uint32_t) duk_get_uint(ctx, -1);
				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
				                     (long) last_index, (long) (last_index + 1)));
				duk_pop(ctx);
				duk_push_int(ctx, last_index + 1);
				duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
			}

			DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_INT_MAX);  /* string limits */
			match_caps = (duk_int_t) duk_get_length(ctx, -1);
		} else {
#else  /* DUK_USE_REGEXP_SUPPORT */
		{  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
			const duk_uint8_t *q_start;               /* match string */
			duk_size_t q_blen;

#ifdef DUK_USE_REGEXP_SUPPORT
			DUK_ASSERT(!is_global);  /* single match always */
#endif

			p_start = DUK_HSTRING_GET_DATA(h_input);
			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
			p = p_start;

			h_search = duk_get_hstring(ctx, 0);
			DUK_ASSERT(h_search != NULL);
			q_start = DUK_HSTRING_GET_DATA(h_search);
			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);

			p_end -= q_blen;  /* ensure full memcmp() fits in while */

			match_start_coff = 0;

			while (p <= p_end) {
				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
				if (DUK_MEMCMP((void *) p, (void *) q_start, (size_t) q_blen) == 0) {
					duk_dup(ctx, 0);
					h_match = duk_get_hstring(ctx, -1);
					DUK_ASSERT(h_match != NULL);
#ifdef DUK_USE_REGEXP_SUPPORT
					match_caps = 0;
#endif
					goto found;
				}

				/* track utf-8 non-continuation bytes */
				if ((p[0] & 0xc0) != 0x80) {
					match_start_coff++;
				}
				p++;
			}

			/* not found */
			break;
		}
	 found:

		/* stack[0] = search value
		 * stack[1] = replace value
		 * stack[2] = input string
		 * stack[3] = result buffer
		 * stack[4] = regexp match OR match string
		 */

		match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);

		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);

		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);

		if (is_repl_func) {
			duk_idx_t idx_args;
			duk_hstring *h_repl;

			/* regexp res_obj is at index 4 */

			duk_dup(ctx, 1);
			idx_args = duk_get_top(ctx);

#ifdef DUK_USE_REGEXP_SUPPORT
			if (is_regexp) {
				duk_int_t idx;
				duk_require_stack(ctx, match_caps + 2);
				for (idx = 0; idx < match_caps; idx++) {
					/* match followed by capture(s) */
					duk_get_prop_index(ctx, 4, idx);
				}
			} else {
#else  /* DUK_USE_REGEXP_SUPPORT */
			{  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
				/* match == search string, by definition */
				duk_dup(ctx, 0);
			}
			duk_push_int(ctx, match_start_coff);
			duk_dup(ctx, 2);

			/* [ ... replacer match [captures] match_char_offset input ] */

			duk_call(ctx, duk_get_top(ctx) - idx_args);
			h_repl = duk_to_hstring(ctx, -1);  /* -> [ ... repl_value ] */
			DUK_ASSERT(h_repl != NULL);

			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);

			duk_pop(ctx);  /* repl_value */
		} else {
			r = r_start;

			while (r < r_end) {
				duk_int_t ch1;
				duk_int_t ch2;
#ifdef DUK_USE_REGEXP_SUPPORT
				duk_int_t ch3;
#endif
				duk_size_t left;

				ch1 = *r++;
				if (ch1 != DUK_ASC_DOLLAR) {
					goto repl_write;
				}
				left = r_end - r;

				if (left <= 0) {
					goto repl_write;
				}

				ch2 = r[0];
				switch ((int) ch2) {
				case DUK_ASC_DOLLAR: {
					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
					goto repl_write;
				}
				case DUK_ASC_AMP: {
					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
					r++;
					continue;
				}
				case DUK_ASC_GRAVE: {
					tmp_sz = (duk_size_t) match_start_boff;
					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
					r++;
					continue;
				}
				case DUK_ASC_SINGLEQUOTE: {
					duk_uint32_t match_end_boff;

					/* Use match charlen instead of bytelen, just in case the input and
					 * match codepoint encodings would have different lengths.
					 */
					match_end_boff = duk_heap_strcache_offset_char2byte(thr,
					                                                    h_input,
					                                                    match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match));

					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
					r++;
					continue;
				}
				default: {
#ifdef DUK_USE_REGEXP_SUPPORT
					duk_int_t capnum, captmp, capadv;
					/* XXX: optional check, match_caps is zero if no regexp,
					 * so dollar will be interpreted literally anyway.
					 */

					if (!is_regexp) {
						goto repl_write;
					}

					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
						goto repl_write;
					}
					capnum = ch2 - DUK_ASC_0;
					capadv = 1;

					if (left >= 2) {
						ch3 = r[1];
						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
							if (captmp < match_caps) {
								capnum = captmp;
								capadv = 2;
							}
						}
					}

					if (capnum > 0 && capnum < match_caps) {
						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */

						/* regexp res_obj is at offset 4 */
						duk_get_prop_index(ctx, 4, (duk_uarridx_t) capnum);
						if (duk_is_string(ctx, -1)) {
							duk_hstring *h_tmp_str;

							h_tmp_str = duk_get_hstring(ctx, -1);
							DUK_ASSERT(h_tmp_str != NULL);

							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
						} else {
							/* undefined -> skip (replaced with empty) */
						}
						duk_pop(ctx);
						r += capadv;
						continue;
					} else {
						goto repl_write;
					}
#else  /* DUK_USE_REGEXP_SUPPORT */
					goto repl_write;  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
				}  /* default case */
				}  /* switch (ch2) */

			 repl_write:
				/* ch1 = (r_increment << 8) + byte */

				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
				r += ch1 >> 8;
			}  /* while repl */
		}  /* if (is_repl_func) */

		duk_pop(ctx);  /* pop regexp res_obj or match string */

#ifdef DUK_USE_REGEXP_SUPPORT
		if (!is_global) {
#else
		{  /* unconditionally; is_global==0 */
#endif
			break;
		}
	}

	/* trailer */
	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);

	DUK_ASSERT_TOP(ctx, 4);
	DUK_BW_COMPACT(thr, bw);
	duk_to_string(ctx, -1);
	return 1;
}

/*
 *  split()
 */

/* XXX: very messy now, but works; clean up, remove unused variables (nomimally
 * used so compiler doesn't complain).
 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hstring *h_input;
	duk_hstring *h_sep;
	duk_uint32_t limit;
	duk_uint32_t arr_idx;
#ifdef DUK_USE_REGEXP_SUPPORT
	duk_bool_t is_regexp;
#endif
	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
	duk_uint32_t match_start_boff, match_start_coff;
	duk_uint32_t match_end_boff, match_end_coff;

	DUK_UNREF(thr);

	h_input = duk_push_this_coercible_to_string(ctx);
	DUK_ASSERT(h_input != NULL);

	duk_push_array(ctx);

	if (duk_is_undefined(ctx, 1)) {
		limit = 0xffffffffUL;
	} else {
		limit = duk_to_uint32(ctx, 1);
	}

	if (limit == 0) {
		return 1;
	}

	/* If the separator is a RegExp, make a "clone" of it.  The specification
	 * algorithm calls [[Match]] directly for specific indices; we emulate this
	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
	 * which will use global-style matching even when the RegExp itself is non-global.
	 */

	if (duk_is_undefined(ctx, 0)) {
		/* The spec algorithm first does "R = ToString(separator)" before checking
		 * whether separator is undefined.  Since this is side effect free, we can
		 * skip the ToString() here.
		 */
		duk_dup(ctx, 2);
		duk_put_prop_index(ctx, 3, 0);
		return 1;
	} else if (duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
#ifdef DUK_USE_REGEXP_SUPPORT
		duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
		duk_dup(ctx, 0);
		duk_new(ctx, 1);  /* [ ... RegExp val ] -> [ ... res ] */
		duk_replace(ctx, 0);
		/* lastIndex is initialized to zero by new RegExp() */
		is_regexp = 1;
#else
		return DUK_RET_UNSUPPORTED_ERROR;
#endif
	} else {
		duk_to_string(ctx, 0);
#ifdef DUK_USE_REGEXP_SUPPORT
		is_regexp = 0;
#endif
	}

	/* stack[0] = separator (string or regexp)
	 * stack[1] = limit
	 * stack[2] = input string
	 * stack[3] = result array
	 */

	prev_match_end_boff = 0;
	prev_match_end_coff = 0;
	arr_idx = 0;
	matched = 0;

	for (;;) {
		/*
		 *  The specification uses RegExp [[Match]] to attempt match at specific
		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
		 *  special variant which forces global-like behavior for matching.
		 */

		DUK_ASSERT_TOP(ctx, 4);

#ifdef DUK_USE_REGEXP_SUPPORT
		if (is_regexp) {
			duk_dup(ctx, 0);
			duk_dup(ctx, 2);
			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
			if (!duk_is_object(ctx, -1)) {
				duk_pop(ctx);
				break;
			}
			matched = 1;

			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
			DUK_ASSERT(duk_is_number(ctx, -1));
			match_start_coff = duk_get_int(ctx, -1);
			match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
			duk_pop(ctx);

			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
				/* don't allow an empty match at the end of the string */
				duk_pop(ctx);
				break;
			}

			duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
			DUK_ASSERT(duk_is_number(ctx, -1));
			match_end_coff = duk_get_int(ctx, -1);
			match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
			duk_pop(ctx);

			/* empty match -> bump and continue */
			if (prev_match_end_boff == match_end_boff) {
				duk_push_int(ctx, match_end_coff + 1);
				duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
				duk_pop(ctx);
				continue;
			}
		} else {
#else  /* DUK_USE_REGEXP_SUPPORT */
		{  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
			const duk_uint8_t *q_start;               /* match string */
			duk_size_t q_blen, q_clen;

			p_start = DUK_HSTRING_GET_DATA(h_input);
			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
			p = p_start + prev_match_end_boff;

			h_sep = duk_get_hstring(ctx, 0);
			DUK_ASSERT(h_sep != NULL);
			q_start = DUK_HSTRING_GET_DATA(h_sep);
			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);

			p_end -= q_blen;  /* ensure full memcmp() fits in while */

			match_start_coff = prev_match_end_coff;

			if (q_blen == 0) {
				/* Handle empty separator case: it will always match, and always
				 * triggers the check in step 13.c.iii initially.  Note that we
				 * must skip to either end of string or start of first codepoint,
				 * skipping over any continuation bytes!
				 *
				 * Don't allow an empty string to match at the end of the input.
				 */

				matched = 1;  /* empty separator can always match */

				match_start_coff++;
				p++;
				while (p < p_end) {
					if ((p[0] & 0xc0) != 0x80) {
						goto found;
					}
					p++;
				}
				goto not_found;
			}

			DUK_ASSERT(q_blen > 0 && q_clen > 0);
			while (p <= p_end) {
				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
				if (DUK_MEMCMP((void *) p, (void *) q_start, (duk_size_t) q_blen) == 0) {
					/* never an empty match, so step 13.c.iii can't be triggered */
					goto found;
				}

				/* track utf-8 non-continuation bytes */
				if ((p[0] & 0xc0) != 0x80) {
					match_start_coff++;
				}
				p++;
			}

		 not_found:
			/* not found */
			break;

		 found:
			matched = 1;
			match_start_boff = (duk_uint32_t) (p - p_start);
			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */

			/* empty match (may happen with empty separator) -> bump and continue */
			if (prev_match_end_boff == match_end_boff) {
				prev_match_end_boff++;
				prev_match_end_coff++;
				continue;
			}
		}  /* if (is_regexp) */

		/* stack[0] = separator (string or regexp)
		 * stack[1] = limit
		 * stack[2] = input string
		 * stack[3] = result array
		 * stack[4] = regexp res_obj (if is_regexp)
		 */

		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
		                     (long) match_start_boff, (long) match_start_coff,
		                     (long) match_end_boff, (long) match_end_coff,
		                     (long) prev_match_end_boff, (long) prev_match_end_coff));

		duk_push_lstring(ctx,
		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
		duk_put_prop_index(ctx, 3, arr_idx);
		arr_idx++;
		if (arr_idx >= limit) {
			goto hit_limit;
		}

#ifdef DUK_USE_REGEXP_SUPPORT
		if (is_regexp) {
			duk_size_t i, len;

			len = duk_get_length(ctx, 4);
			for (i = 1; i < len; i++) {
				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
				duk_get_prop_index(ctx, 4, (duk_uarridx_t) i);
				duk_put_prop_index(ctx, 3, arr_idx);
				arr_idx++;
				if (arr_idx >= limit) {
					goto hit_limit;
				}
			}

			duk_pop(ctx);
			/* lastIndex already set up for next match */
		} else {
#else  /* DUK_USE_REGEXP_SUPPORT */
		{  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
			/* no action */
		}

		prev_match_end_boff = match_end_boff;
		prev_match_end_coff = match_end_coff;
		continue;
	}  /* for */

	/* Combined step 11 (empty string special case) and 14-15. */

	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
	                     (long) prev_match_end_boff, (long) prev_match_end_coff));

	if (DUK_HSTRING_GET_CHARLEN(h_input) > 0 || !matched) {
		/* Add trailer if:
		 *   a) non-empty input
		 *   b) empty input and no (zero size) match found (step 11)
		 */

		duk_push_lstring(ctx,
		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
		duk_put_prop_index(ctx, 3, arr_idx);
		/* No arr_idx update or limit check */
	}

	return 1;

 hit_limit:
#ifdef DUK_USE_REGEXP_SUPPORT
	if (is_regexp) {
		duk_pop(ctx);
	}
#endif

	return 1;
}

/*
 *  Various
 */

#ifdef DUK_USE_REGEXP_SUPPORT
DUK_LOCAL void duk__to_regexp_helper(duk_context *ctx, duk_idx_t index, duk_bool_t force_new) {
	duk_hobject *h;

	/* Shared helper for match() steps 3-4, search() steps 3-4. */

	DUK_ASSERT(index >= 0);

	if (force_new) {
		goto do_new;
	}

	h = duk_get_hobject_with_class(ctx, index, DUK_HOBJECT_CLASS_REGEXP);
	if (!h) {
		goto do_new;
	}
	return;

 do_new:
	duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
	duk_dup(ctx, index);
	duk_new(ctx, 1);  /* [ ... RegExp val ] -> [ ... res ] */
	duk_replace(ctx, index);
}
#endif  /* DUK_USE_REGEXP_SUPPORT */

#ifdef DUK_USE_REGEXP_SUPPORT
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
	duk_hthread *thr = (duk_hthread *) ctx;

	/* Easiest way to implement the search required by the specification
	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
	 * side effects on the argument, "clone" the RegExp if a RegExp was
	 * given as input.
	 *
	 * The global flag of the RegExp should be ignored; setting lastIndex
	 * to zero (which happens when "cloning" the RegExp) should have an
	 * equivalent effect.
	 */

	DUK_ASSERT_TOP(ctx, 1);
	(void) duk_push_this_coercible_to_string(ctx);  /* at index 1 */
	duk__to_regexp_helper(ctx, 0 /*index*/, 1 /*force_new*/);

	/* stack[0] = regexp
	 * stack[1] = string
	 */

	/* Avoid using RegExp.prototype methods, as they're writable and
	 * configurable and may have been changed.
	 */

	duk_dup(ctx, 0);
	duk_dup(ctx, 1);  /* [ ... re_obj input ] */
	duk_regexp_match(thr);  /* -> [ ... res_obj ] */

	if (!duk_is_object(ctx, -1)) {
		duk_push_int(ctx, -1);
		return 1;
	}

	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
	DUK_ASSERT(duk_is_number(ctx, -1));
	return 1;
}
#else  /* DUK_USE_REGEXP_SUPPORT */
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
	DUK_UNREF(ctx);
	return DUK_RET_UNSUPPORTED_ERROR;
}
Exemplo n.º 28
0
void test(duk_context *ctx) {
	int i, n;

	/* 0 */
	duk_push_string(ctx, "foo");

	/* 1 */
	duk_push_string(ctx, "\xe1\x88\xb4xyz");  /* 4 chars, first char utf-8 encoded U+1234 */

	/* 2 */
	duk_push_object(ctx);  /* no length property */

	/* 3 */
	duk_push_object(ctx);  /* length: 123 */
	duk_push_int(ctx, 123);
	duk_put_prop_string(ctx, -2, "length");

	/* 4 */
	duk_push_object(ctx);  /* length: "bar" */
	duk_push_string(ctx, "bar");
	duk_put_prop_string(ctx, -2, "length");

	/* 5 */
	duk_push_object(ctx);  /* length: 123.9, fractional number */
	duk_push_number(ctx, 123.9);
	duk_put_prop_string(ctx, -2, "length");

	/* 6 */
	duk_push_object(ctx);  /* length: negative but within 32-bit range after ToInteger() */
	duk_push_number(ctx, -0.9);
	duk_put_prop_string(ctx, -2, "length");

	/* 7 */
	duk_push_object(ctx);  /* length: negative, outside 32-bit range */
	duk_push_number(ctx, -1);
	duk_put_prop_string(ctx, -2, "length");

	/* 8 */
	duk_push_object(ctx);  /* length: outside 32-bit range but within range after ToInteger() */
	duk_push_number(ctx, 4294967295.9);
	duk_put_prop_string(ctx, -2, "length");

	/* 9 */
	duk_push_object(ctx);  /* length: outside 32-bit range */
	duk_push_number(ctx, 4294967296);
	duk_put_prop_string(ctx, -2, "length");

	/* 10 */
	duk_push_object(ctx);  /* length: nan */
	duk_push_nan(ctx);
	duk_put_prop_string(ctx, -2, "length");

	/* 11 */
	duk_push_object(ctx);  /* length: +Infinity */
	duk_push_number(ctx, INFINITY);
	duk_put_prop_string(ctx, -2, "length");

	/* 12 */
	duk_push_object(ctx);  /* length: -Infinity */
	duk_push_number(ctx, -INFINITY);
	duk_put_prop_string(ctx, -2, "length");

	/* 13 */
	duk_push_fixed_buffer(ctx, 1234);

	/* 14 */
	duk_push_dynamic_buffer(ctx, 2345);

	/* 15 */
	duk_push_undefined(ctx);

	/* 16 */
	duk_push_null(ctx);

	/* 17 */
	duk_push_true(ctx);

	/* 18 */
	duk_push_false(ctx);

	n = duk_get_top(ctx);
	printf("top: %d\n", n);
	for (i = 0; i < n; i++) {
		printf("index %d: length %u\n", i, (unsigned int) duk_get_length(ctx, i));
	}
}
Exemplo n.º 29
0
//-----------------------------------------------------------------------------
void AdTiledManager::Load(const char* pName) {
	Unload();

	char pFN[FILENAME_MAX];
	sprintf(pFN, MAP_LOCATION, pName);

	duk_context* ctx = s_pJSCtx;

	duk_push_string_file(ctx, pFN);
	duk_json_decode(ctx, -1);

	if(!duk_is_object(ctx, -1)) {
		fprintf(stderr, "NOTE: Failed parse %s.json!\n", pName);
		return;
	}
	
	duk_get_prop_string(ctx, -1, "width");
	m_iWidth = duk_to_int(ctx, -1);
	duk_pop(ctx);

	duk_get_prop_string(ctx, -1, "height");
	m_iHeight = duk_to_int(ctx, -1);
	duk_pop(ctx);

	duk_get_prop_string(ctx, -1, "layers");
	
	if(duk_is_array(ctx, -1)) {
		m_nLayers  = duk_get_length(ctx, -1);
		m_pIndices = (int**) calloc(m_nLayers, sizeof(int*));

		for(int j=0; j<m_nLayers; ++j) {
			duk_get_prop_index(ctx, -1, j);

			// NOTE: if this is a tile layer grab the indices, otherwise set
			// to NULL
			duk_get_prop_string(ctx, -1, "data");

			if(duk_is_array(ctx, -1)) {
				int size = duk_get_length(ctx, -1);

				if((m_iWidth*m_iHeight) == size) {
					m_pIndices[j] = (int*) malloc(size*sizeof(int));

					for(int i=0; i<size; ++i) {
						duk_get_prop_index(ctx, -1, i);
						m_pIndices[j][i] = duk_to_int(ctx, -1);
						duk_pop(ctx);
					}
				}
			}

			duk_pop(ctx);

			// NOTE: loop over the map entities and add them to the array of
			// entities
			duk_get_prop_string(ctx, -1, "name");

			if(duk_is_string(ctx, -1)) {
				if(!strcmp(duk_get_string(ctx, -1), "entities")) {
					// NOTE: -2 referring back to object and not the string
					duk_get_prop_string(ctx, -2, "objects");

					if(duk_is_array(ctx, -1)) {
						int size = duk_get_length(ctx, -1);
						
						for(int e=0; e<size; ++e) {
							duk_get_prop_index(ctx, -1, e);

							duk_get_prop_string(ctx, -1, "type");
							const char* type = duk_get_string(ctx, -1);

							AdEntity* pEnt = NULL;

							if(!strcmp(type, "NPC-TEST")) {
								duk_pop(ctx);
								pEnt = new NpcTree0();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-RON")) {
								duk_pop(ctx);
								pEnt = new NpcRon();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-PYTHON")) {
								duk_pop(ctx);
								pEnt = new NpcPython();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-BURRITO")) {
								duk_pop(ctx);
								pEnt = new NpcBurrito();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-JAVALS")) {
								duk_pop(ctx);
								pEnt = new NpcJavals();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-GWEN")) {
								duk_pop(ctx);
								pEnt = new NpcGwen();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-AVOCADO")) {
								duk_pop(ctx);
								pEnt = new NpcAvocado();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-PUZZLE_PIECE")) {
								duk_pop(ctx);
								pEnt = new NpcPuzzlePiece();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-PUZZLE_PIECE2")) {
								duk_pop(ctx);
								pEnt = new NpcPuzzlePiece2();
								pEnt->Load(ctx);
							} else if(!strcmp(type, "NPC-STATUE_BASE")) {
								duk_pop(ctx);
								pEnt = new NpcStatueBase();
								pEnt->Load(ctx);
							} else if(
								!strcmp(type, "LVL-UP-0")    ||
								!strcmp(type, "LVL-DOWN-0")  ||
								!strcmp(type, "LVL-LEFT-0")  ||
								!strcmp(type, "LVL-RIGHT-0")
							) {
								duk_pop(ctx);
								pEnt = new AdEntity();
								pEnt->Load(ctx);
							} else {
								duk_pop(ctx);
							}

							if(pEnt) {
								m_pEntities = (AdEntity**) realloc(
									m_pEntities, ++m_nEntities*sizeof(AdEntity*)
								); m_pEntities[m_nEntities-1] = pEnt;
							}

							duk_pop(ctx);
						}
					}

					duk_pop(ctx);
				}
			}

			duk_pop_2(ctx);
		}
	}

	duk_pop_2(ctx);
}
Exemplo n.º 30
0
//duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index);
duk_size_t aperl_duk_get_length(duk_context *ctx, duk_idx_t index) {
	duk_size_t ret = duk_get_length(ctx, index);
	return ret;
}