Beispiel #1
0
static duk_ret_t test_pop_na(duk_context *ctx, void *udata) {
	(void) udata;

	duk_pop_n(ctx, 0);
	PRINTTOP();

	duk_pop_n(ctx, 1);
	PRINTTOP();

	duk_pop_n(ctx, 10);
	PRINTTOP();

	return 0;
}
Beispiel #2
0
/* duk_get_prop(), test in API doc (more or less) */
static duk_ret_t test_1d(duk_context *ctx) {
	int cfg_idx;

	prep(ctx);

	/* reading [global object].Math.PI */
	duk_push_global_object(ctx);    /* -> [ global ] */
	duk_push_string(ctx, "Math");   /* -> [ global "Math" ] */
	duk_get_prop(ctx, -2);          /* -> [ global Math ] */
	duk_push_string(ctx, "PI");     /* -> [ global Math "PI" ] */
	duk_get_prop(ctx, -2);          /* -> [ global Math PI ] */
	printf("Math.PI is %lf\n", duk_get_number(ctx, -1));
	duk_pop_n(ctx, 3);

	/* fake config object */
	cfg_idx = duk_get_top(ctx);
	duk_push_string(ctx, "{\"mySetting\": \"setting value\"}");
	duk_json_decode(ctx, cfg_idx);

	/* reading a configuration value, cfg_idx is normalized
	 * index of a configuration object.
	 */
	duk_push_string(ctx, "mySetting");
	if (duk_get_prop(ctx, cfg_idx)) {
	    const char *str_value = duk_to_string(ctx, -1);
	    printf("configuration setting present, value: %s\n", str_value);
	} else {
	    printf("configuration setting missing\n");
	}
	duk_pop(ctx);  /* remember to pop, regardless of whether or not present */

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Beispiel #3
0
				//ÊÖ„Ó pop
				void reset()
				{
					if(_n == 0)
					{
						_ctx_ptr = NULL;
						if(_ctx)
						{
							_ctx.reset();
						}
						return;
					}
					if(_ctx_ptr == NULL)
					{
						_ctx_ptr = _ctx;
					}
					if(_n == 1)
					{
						duk_pop(_ctx_ptr);
					}
					else
					{
						duk_pop_n(_ctx_ptr,_n);
					}

					_n = 0;
					_ctx_ptr = NULL;
					if(_ctx)
					{
						_ctx.reset();
					}
				}
Beispiel #4
0
// Assumes nargs are the top of the stack.  Rest comes from request
// Return value is not left on the stack.
void duv_resolve(uv_req_t* req, int nargs) {
  duk_context *ctx = req->data;
  duv_push_handle(ctx, req);
  // stack: args... obj
  duk_get_prop_string(ctx, -1, "\xff""uv-callback");
  // stack: args... obj callback
  duk_del_prop_string(ctx, -2, "\xff""uv-callback");
  // stack: args... obj callback

  if (!duk_is_function(ctx, -1)) {
    // stack: args... obj callback
    duk_pop_n(ctx, 2 + nargs);
    return;
  }
  duk_remove(ctx, -2);
  // stack: args... callback
  duk_insert(ctx, -(nargs + 1));
  // stack: callback args...
  duk_call(ctx, nargs);
  // stack: result
  duk_pop(ctx);

  // Remove the request from the GC roots
  duv_remove_handle(ctx, req);
}
Beispiel #5
0
static int sys1_poll(duk_context *ctx)
{
	int nfds = duk_to_int(ctx, 1);
	int timeout = duk_to_int(ctx, 2);
	int i, rc;
	struct pollfd *fds;

	fds = malloc(sizeof(struct pollfd)*nfds);
	memset(fds, 0, sizeof(struct pollfd)*nfds);
	
	for(i=0;i<nfds;i++) {
		duk_get_prop_index(ctx, 0, i);
		duk_get_prop_string(ctx, 3, "fd");	
		fds[i].fd = duk_to_int(ctx, 4);
		duk_get_prop_string(ctx, 3, "events");	
		fds[i].events = duk_to_int(ctx, 5);
		duk_pop_n(ctx, 3);
	}

	rc = poll(fds, nfds, timeout);
	duk_push_object(ctx);
	duk_push_int(ctx, rc);
	duk_put_prop_string(ctx, -2, "rc");
	duk_dup(ctx, 0); // dup reference to arg0 array
	for(i=0;i<nfds;i++) {
		duk_get_prop_index(ctx, -1, i); // fetch object from array at i
		duk_push_int(ctx, fds[i].revents);
		duk_put_prop_string(ctx, -2, "revents"); // put revents into object
		duk_pop(ctx); // remove object from stack
	}
	duk_put_prop_string(ctx, -2, "fds");

	return 1;
}
void
_gum_duk_create_subclass (duk_context * ctx,
                          const gchar * parent,
                          const gchar * name,
                          duk_c_function constructor,
                          gint constructor_nargs,
                          duk_c_function finalize)
{
  duk_push_global_object (ctx);
  duk_get_prop_string (ctx, -1, "Object");
  duk_get_prop_string (ctx, -1, "create");

  duk_get_prop_string (ctx, -3, parent);
  duk_get_prop_string (ctx, -1, "prototype");
  duk_dup (ctx, -3);
  duk_dup (ctx, -2);
  duk_call (ctx, 1);

  if (constructor != NULL)
    duk_push_c_function (ctx, constructor, constructor_nargs);
  else
    duk_push_object (ctx);

  duk_dup (ctx, -2);
  if (finalize != NULL)
  {
    duk_push_c_function (ctx, finalize, 2);
    duk_set_finalizer (ctx, -2);
  }
  duk_put_prop_string (ctx, -2, "prototype");
  duk_put_prop_string (ctx, -7, name);
  duk_pop_n (ctx, 6);
}
/* It's not an error for the underlying plain buffer to be too small to
 * cover the slice.  This is allowed because it may happen for dynamic
 * and external buffers at run time anyway.  In any case, no memory
 * unsafe behavior happens.
 */
static duk_ret_t test_uncovered(duk_context *ctx, void *udata) {
	(void) udata;

	duk_push_fixed_buffer(ctx, 256);
	duk_push_buffer_object(ctx, -1, 7, 512, DUK_BUFOBJ_UINT32ARRAY);

	duk_eval_string(ctx, "dumpBufferInfo");
	duk_dup(ctx, -2);
	duk_call(ctx, 1);
	duk_pop(ctx);

	duk_eval_string(ctx,
		"(function (v) {\n"
		"    for (var i = 0; i < v.length; i++) { v[i] = 123; }\n"
		"    for (var i = 0; i < v.length; i++) { var ignore = v[i]; }\n"
		"})");
	duk_dup(ctx, -2);
	duk_call(ctx, 1);
	duk_pop(ctx);

	duk_pop_n(ctx, 2);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 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;
}
static duk_ret_t test_basic(duk_context *ctx, void *udata) {
	duk_uint_t test[] = {
		DUK_BUFOBJ_NODEJS_BUFFER,
		DUK_BUFOBJ_ARRAYBUFFER,
		DUK_BUFOBJ_DATAVIEW,
		DUK_BUFOBJ_INT8ARRAY,
		DUK_BUFOBJ_UINT8ARRAY,
		DUK_BUFOBJ_UINT8CLAMPEDARRAY,
		DUK_BUFOBJ_INT16ARRAY,
		DUK_BUFOBJ_UINT16ARRAY,
		DUK_BUFOBJ_INT32ARRAY,
		DUK_BUFOBJ_UINT32ARRAY,
		DUK_BUFOBJ_FLOAT32ARRAY,
		DUK_BUFOBJ_FLOAT64ARRAY,
	};
	int i;
	unsigned char extbuf[256];

	(void) udata;

	for (i = 0; i < sizeof(test) / sizeof(duk_uint_t); i++) {
		switch (i % 3) {
		case 0:
			duk_push_fixed_buffer(ctx, 256);
			break;
		case 1:
			duk_push_dynamic_buffer(ctx, 256);
			break;
		case 2:
			duk_push_external_buffer(ctx);
			duk_config_buffer(ctx, -1, (void *) extbuf, 256);
			break;
		}

		duk_push_undefined(ctx);  /* dummy */

		duk_push_buffer_object(ctx, -2, 128, 32, test[i]);

		duk_eval_string(ctx, "dumpBufferInfo");
		duk_dup(ctx, -2);
		duk_call(ctx, 1);

		/* ... plain undefined bufferobject result */
		duk_pop_n(ctx, 4);
	}

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
/* Normally typed array constructors require that the slice begin at a multiple
 * of the element size (e.g. 4 bytes for Uint32Array) and that the slice ends
 * evenly.  The C API doesn't pose such restrictions.
 */
static duk_ret_t test_unaligned(duk_context *ctx, void *udata) {
	(void) udata;

	duk_push_fixed_buffer(ctx, 256);
	duk_push_buffer_object(ctx, -1, 7, 64, DUK_BUFOBJ_UINT32ARRAY);

	duk_eval_string(ctx, "dumpBufferInfo");
	duk_dup(ctx, -2);
	duk_call(ctx, 1);
	duk_pop(ctx);

	duk_pop_n(ctx, 2);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Beispiel #11
0
/*
 * Fulfill a libuv request.
 */
void
mn_fulfill_req(duk_context *ctx, uv_req_t *req, int nargs) {
	mn_req_t *data = req->data;
	if (data->callback_ref) {
		mn_push_ref(ctx, data->callback_ref);
		if (nargs) {
			duk_insert(ctx, -1 - nargs);
		}
		mn_push_ref(ctx, data->context);
		if (nargs) {
			duk_insert(ctx, -1 - nargs);
		}
		duk_call_method(ctx, nargs);
		duk_pop(ctx);
	} else if (nargs) {
		duk_pop_n(ctx, nargs);
	}
}
static duk_ret_t test_expand_overlap(duk_context *ctx, void *udata) {
	unsigned char buf[48];
	int offset;
	int i;

	(void) udata;

	for (offset = 0; offset < 16; offset++) {  /* dst offset */
		printf("offset: %d\n", offset);

		for (i = 0; i < 48; i++) {
			buf[i] = (unsigned char) i;
		}

		duk_push_external_buffer(ctx);  /* src */
		duk_config_buffer(ctx, -1, (void *) (buf + 4), 4);  /* |04050607| */

		duk_push_external_buffer(ctx);  /* dst */
		duk_config_buffer(ctx, -1, (void *) (buf + offset), 32);

		duk_eval_string(ctx,
			"(function (plain_src, plain_dst) {\n"
			"    var bsrc = new Uint8Array(plain_src.buffer);\n"
			"    var bdst = new Uint32Array(plain_dst.buffer);\n"
			"    print(Duktape.enc('jx', bsrc));\n"
			"    print(Duktape.enc('jx', bdst));\n"
			"    bdst.set(bsrc, 1);\n"
			"    print(Duktape.enc('jx', bsrc));\n"
			"    print(Duktape.enc('jx', bdst));\n"
			"})");
		duk_dup(ctx, 0);
		duk_dup(ctx, 1);
		duk_call(ctx, 2);
		duk_pop_n(ctx, 3);

		for (i = 0; i < 48; i++) {
			printf("%02x", (unsigned int) buf[i]);
		}
		printf("\n");
	}

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
/* Normally typed array constructors require that the slice begin at a multiple
 * of the element size (e.g. 4 bytes for Uint32Array) and that the slice ends
 * evenly.  The C API doesn't pose such restrictions; the .length (number of
 * elements) will become the number of full elements allowed by the slice.
 * The .byteOffset and .byteLength will reflect the call arguments, e.g.
 * .byteLength is 63 here, which means that .length x .BYTES_PER_ELEMENT
 * won't match .byteLength in this case.
 */
static duk_ret_t test_unaligned_uneven(duk_context *ctx, void *udata) {
	(void) udata;

	/* Start at an unaligned offset, with slice length NOT a multiple
	 * of 4.
	 */
	duk_push_fixed_buffer(ctx, 256);
	duk_push_buffer_object(ctx, -1, 7, 63, DUK_BUFOBJ_UINT32ARRAY);

	duk_eval_string(ctx, "dumpBufferInfo");
	duk_dup(ctx, -2);
	duk_call(ctx, 1);
	duk_pop(ctx);

	duk_pop_n(ctx, 2);

	printf("final top: %ld\n", (long) duk_get_top(ctx));
	return 0;
}
Beispiel #14
0
void duv_emit(uv_handle_t* handle, const char* key, int nargs, int cleanup) {
  duk_context *ctx = handle->data;
  duv_push_handle(ctx, handle);
  // stack: args... this
  duk_get_prop_string(ctx, -1, key);
  // stack: args... this fn
  if (cleanup) duk_del_prop_string(ctx, -2, key);
  // stack: args... this fn
  if (!duk_is_function(ctx, -1)) {
    duk_pop_n(ctx, 2 + nargs);
    return;
  }
  duk_insert(ctx, -(nargs + 2));
  // stack: fn args... this
  duk_insert(ctx, -(nargs + 1));
  // stack: fn this args...
  duk_call_method(ctx, nargs);
  // stack: result
  duk_pop(ctx);
}
int UI_DebugGetUIKeepAliveCount(duk_context* ctx)
{
    duk_push_global_stash(ctx);
    duk_get_prop_string(ctx, -1, "__jsui_widgetkeepalive");

    duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);

    double count = 0;

    while (duk_next(ctx, -1 , 0)) {

        duk_pop(ctx);  /* pop_key */
        count++;
    }

    duk_pop_n(ctx, 3);  /* pop enum object, keep alive object, and stash */

    duk_push_number(ctx, count);

    return 1;
}
Beispiel #16
0
void
mn_emit_event(
	duk_context *ctx,
	mn_handle_t *data,
	mn_cb_id_t type,
	int nargs
) {
	int fn_ref = data->callbacks[type];
	if (fn_ref) {
		mn_push_ref(ctx, fn_ref);
		if (nargs) {
			duk_insert(ctx, -1 - nargs);
		}
		mn_push_ref(ctx, data->context);
		if (nargs) {
			duk_insert(ctx, -1 - nargs);
		}
		duk_call_method(ctx, nargs);
		duk_pop(ctx);
	} else if (nargs) {
		duk_pop_n(ctx, nargs);
	}
}
void duk_hthread_create_builtin_objects(duk_hthread *thr) {
	duk_context *ctx = (duk_context *) thr;
	duk_bitdecoder_ctx bd_ctx;
	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
	duk_hobject *h;
	int i, j;

	DUK_DPRINT("INITBUILTINS BEGIN");

	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
	bd->data = (const duk_uint8_t *) duk_builtins_data;
	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;

	/*
	 *  First create all built-in bare objects on the empty valstack.
	 *  During init, their indices will correspond to built-in indices.
	 *
	 *  Built-ins will be reachable from both valstack and thr->builtins.
	 */

	/* XXX: there is no need to resize valstack because builtin count
	 * is much less than the default space; assert for it.
	 */

	DUK_DDPRINT("create empty built-ins");
	DUK_ASSERT_TOP(ctx, 0);
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		int class_num;
		int len = -1;

		class_num = duk_bd_decode(bd, DUK__CLASS_BITS);
		len = duk_bd_decode_flagged(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);

		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
			int natidx;
			int stridx;
			int c_nargs;
			duk_c_function c_func;
			duk_int16_t magic;

			DUK_DDDPRINT("len=%d", len);
			DUK_ASSERT(len >= 0);

			natidx = duk_bd_decode(bd, DUK__NATIDX_BITS);
			stridx = duk_bd_decode(bd, DUK__STRIDX_BITS);
			c_func = duk_bi_native_functions[natidx];

			c_nargs = duk_bd_decode_flagged(bd, DUK__NARGS_BITS, len /*def_value*/);
			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
				c_nargs = DUK_VARARGS;
			}

			/* FIXME: set magic directly here? (it could share the c_nargs arg) */
			duk_push_c_function_nospecial(ctx, c_func, c_nargs);

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

			/* Currently all built-in native functions are strict.
			 * duk_push_c_function() now sets strict flag, so
			 * assert for it.
			 */
			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));

			/* FIXME: function properties */

			duk_push_hstring_stridx(ctx, stridx);
			duk_def_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);

			/* Almost all global level Function objects are constructable
			 * but not all: Function.prototype is a non-constructable,
			 * callable Function.
			 */
			if (duk_bd_decode_flag(bd)) {
				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
			} else {
				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
			}

			/* Cast converts magic to 16-bit signed value */
			magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0 /*def_value*/);
			((duk_hnativefunction *) h)->magic = magic;
		} else {
			/* FIXME: ARRAY_PART for Array prototype? */

			duk_push_object_helper(ctx,
			                       DUK_HOBJECT_FLAG_EXTENSIBLE,
			                       -1);  /* no prototype or class yet */

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

		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);

		thr->builtins[i] = h;
		DUK_HOBJECT_INCREF(thr, &h->hdr);

		if (len >= 0) {
			/*
			 *  For top-level objects, 'length' property has the following
			 *  default attributes: non-writable, non-enumerable, non-configurable
			 *  (E5 Section 15).
			 *
			 *  However, 'length' property for Array.prototype has attributes
			 *  expected of an Array instance which are different: writable,
			 *  non-enumerable, non-configurable (E5 Section 15.4.5.2).
			 *
			 *  This is currently determined implicitly based on class; there are
			 *  no attribute flags in the init data.
			 */

			duk_push_int(ctx, len);
			duk_def_prop_stridx(ctx,
			                    -2,
			                    DUK_STRIDX_LENGTH,
			                    (class_num == DUK_HOBJECT_CLASS_ARRAY ?  /* only Array.prototype matches */
			                     DUK_PROPDESC_FLAGS_W : DUK_PROPDESC_FLAGS_NONE));
		}

		/* enable special behaviors last */

		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
			DUK_HOBJECT_SET_SPECIAL_ARRAY(h);
		}
		if (class_num == DUK_HOBJECT_CLASS_STRING) {
			DUK_HOBJECT_SET_SPECIAL_STRINGOBJ(h);
		}

		/* some assertions */

		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPILEDFUNCTION(h));
		/* DUK_HOBJECT_FLAG_NATIVEFUNCTION varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h));       /* currently, even for Array.prototype */
		/* DUK_HOBJECT_FLAG_STRICT varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(h) ||  /* all native functions have NEWENV */
		           DUK_HOBJECT_HAS_NEWENV(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_ENVRECCLOSED(h));
		/* DUK_HOBJECT_FLAG_SPECIAL_ARRAY varies */
		/* DUK_HOBJECT_FLAG_SPECIAL_STRINGOBJ varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_SPECIAL_ARGUMENTS(h));

		DUK_DDDPRINT("created built-in %d, class=%d, length=%d", i, class_num, len);
	}

	/*
	 *  Then decode the builtins init data (see genbuiltins.py) to
	 *  init objects
	 */

	DUK_DDPRINT("initialize built-in object properties");
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		unsigned char t;
		int num;

		DUK_DDDPRINT("initializing built-in object at index %d", i);
		h = thr->builtins[i];

		t = duk_bd_decode(bd, DUK__BIDX_BITS);
		if (t != DUK__NO_BIDX_MARKER) {
			DUK_DDDPRINT("set internal prototype: built-in %d", (int) t);
			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[t]);
		}

		t = duk_bd_decode(bd, DUK__BIDX_BITS);
		if (t != DUK__NO_BIDX_MARKER) {
			/* 'prototype' property for all built-in objects (which have it) has attributes:
			 *  [[Writable]] = false,
			 *  [[Enumerable]] = false,
			 *  [[Configurable]] = false
			 */
			DUK_DDDPRINT("set external prototype: built-in %d", (int) t);
			duk_def_prop_stridx_builtin(ctx, i, DUK_STRIDX_PROTOTYPE, t, DUK_PROPDESC_FLAGS_NONE);
		}

		t = duk_bd_decode(bd, DUK__BIDX_BITS);
		if (t != DUK__NO_BIDX_MARKER) {
			/* 'constructor' property for all built-in objects (which have it) has attributes:
			 *  [[Writable]] = true,
			 *  [[Enumerable]] = false,	
			 *  [[Configurable]] = true
			 */
			DUK_DDDPRINT("set external constructor: built-in %d", (int) t);
			duk_def_prop_stridx_builtin(ctx, i, DUK_STRIDX_CONSTRUCTOR, t, DUK_PROPDESC_FLAGS_WC);
		}

		/* normal valued properties */
		num = duk_bd_decode(bd, DUK__NUM_NORMAL_PROPS_BITS);
		DUK_DDDPRINT("built-in object %d, %d normal valued properties", i, num);
		for (j = 0; j < num; j++) {
			int stridx;
			int prop_flags;

			stridx = duk_bd_decode(bd, DUK__STRIDX_BITS);

			/*
			 *  Property attribute defaults are defined in E5 Section 15 (first
			 *  few pages); there is a default for all properties and a special
			 *  default for 'length' properties.  Variation from the defaults is
			 *  signaled using a single flag bit in the bitstream.
			 */

			if (duk_bd_decode_flag(bd)) {
				prop_flags = duk_bd_decode(bd, DUK__PROP_FLAGS_BITS);
			} else {
				if (stridx == DUK_STRIDX_LENGTH) {
					prop_flags = DUK_PROPDESC_FLAGS_NONE;
				} else {
					prop_flags = DUK_PROPDESC_FLAGS_WC;
				}
			}

			t = duk_bd_decode(bd, DUK__PROP_TYPE_BITS);

			DUK_DDDPRINT("built-in %d, normal-valued property %d, stridx %d, flags 0x%02x, type %d",
			             i, j, stridx, prop_flags, (int) t);

			switch (t) {
			case DUK__PROP_TYPE_DOUBLE: {
				duk_double_union du;
				int k;

				for (k = 0; k < 8; k++) {
					/* Encoding endianness must match target memory layout,
					 * build scripts and genbuiltins.py must ensure this.
					 */
					du.uc[k] = (duk_uint8_t) duk_bd_decode(bd, 8);
				}

				duk_push_number(ctx, du.d);  /* push operation normalizes NaNs */
				break;
			}
			case DUK__PROP_TYPE_STRING: {
				int n;
				int k;
				char *p;

				n = duk_bd_decode(bd, DUK__STRING_LENGTH_BITS);
				p = (char *) duk_push_fixed_buffer(ctx, n);
				for (k = 0; k < n; k++) {
					*p++ = duk_bd_decode(bd, DUK__STRING_CHAR_BITS);
				}

				duk_to_string(ctx, -1);
				break;
			}
			case DUK__PROP_TYPE_STRIDX: {
				int n;

				n = duk_bd_decode(bd, DUK__STRIDX_BITS);
				DUK_ASSERT(n >= 0 && n < DUK_HEAP_NUM_STRINGS);
				duk_push_hstring_stridx(ctx, n);
				break;
			}
			case DUK__PROP_TYPE_BUILTIN: {
				int bidx;

				bidx = duk_bd_decode(bd, DUK__BIDX_BITS);
				DUK_ASSERT(bidx != DUK__NO_BIDX_MARKER);
				duk_dup(ctx, bidx);
				break;
			}
			case DUK__PROP_TYPE_UNDEFINED: {
				duk_push_undefined(ctx);
				break;
			}
			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
				duk_push_true(ctx);
				break;
			}
			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
				duk_push_false(ctx);
				break;
			}
			case DUK__PROP_TYPE_ACCESSOR: {
				int natidx_getter = duk_bd_decode(bd, DUK__NATIDX_BITS);
				int natidx_setter = duk_bd_decode(bd, DUK__NATIDX_BITS);
				duk_c_function c_func_getter;
				duk_c_function c_func_setter;

				/* XXX: this is a bit awkward because there is no exposed helper
				 * in the API style, only this internal helper.
				 */
				DUK_DDDPRINT("built-in accessor property: objidx=%d, stridx=%d, getteridx=%d, setteridx=%d, flags=0x%04x",
				             i, stridx, natidx_getter, natidx_setter, prop_flags);

				c_func_getter = duk_bi_native_functions[natidx_getter];
				c_func_setter = duk_bi_native_functions[natidx_setter];
				duk_push_c_function_noconstruct_nospecial(ctx, c_func_getter, 0);  /* always 0 args */
				duk_push_c_function_noconstruct_nospecial(ctx, c_func_setter, 1);  /* always 1 arg */

				/* FIXME: magic for getter/setter? */

				prop_flags |= DUK_PROPDESC_FLAG_ACCESSOR;  /* accessor flag not encoded explicitly */
				duk_hobject_define_accessor_internal(thr,
				                                     duk_require_hobject(ctx, i),
				                                     DUK_HTHREAD_GET_STRING(thr, stridx),
				                                     duk_require_hobject(ctx, -2),
				                                     duk_require_hobject(ctx, -1),
				                                     prop_flags);
				duk_pop_2(ctx);  /* getter and setter, now reachable through object */
				goto skip_value;
			}
			default: {
				/* exhaustive */
				DUK_UNREACHABLE();
			}
			}

			DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0);
			duk_def_prop_stridx(ctx, i, stridx, prop_flags);

		 skip_value:
			continue;  /* avoid empty label at the end of a compound statement */
		}

		/* native function properties */
		num = duk_bd_decode(bd, DUK__NUM_FUNC_PROPS_BITS);
		DUK_DDDPRINT("built-in object %d, %d function valued properties", i, num);
		for (j = 0; j < num; j++) {
			int stridx;
			int natidx;
			int c_nargs;
			int c_length;
			duk_int16_t magic;
			duk_c_function c_func;
			duk_hnativefunction *h_func;

			stridx = duk_bd_decode(bd, DUK__STRIDX_BITS);
			natidx = duk_bd_decode(bd, DUK__NATIDX_BITS);

			c_length = duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
			c_nargs = duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_int32_t) c_length /*def_value*/);
			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
				c_nargs = DUK_VARARGS;
			}

			c_func = duk_bi_native_functions[natidx];

			DUK_DDDPRINT("built-in %d, function-valued property %d, stridx %d, natidx %d, length %d, nargs %d",
			             i, j, stridx, natidx, c_length, (c_nargs == DUK_VARARGS ? -1 : c_nargs));

			/* [ (builtin objects) ] */

			duk_push_c_function_noconstruct_nospecial(ctx, c_func, c_nargs);
			h_func = duk_require_hnativefunction(ctx, -1);
			DUK_UNREF(h_func);

			/* Currently all built-in native functions are strict.
			 * This doesn't matter for many functions, but e.g.
			 * String.prototype.charAt (and other string functions)
			 * rely on being strict so that their 'this' binding is
			 * not automatically coerced.
			 */
			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);

			/* No built-in functions are constructable except the top
			 * level ones (Number, etc).
			 */
			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));

			/* FIXME: any way to avoid decoding magic bit; there are quite
			 * many function properties and relatively few with magic values.
			 */
			/* Cast converts magic to 16-bit signed value */
			magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0);
			h_func->magic = magic;

			/* [ (builtin objects) func ] */

			duk_push_int(ctx, c_length);
			duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);

			duk_push_hstring_stridx(ctx, stridx);
			duk_def_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);

			/* FIXME: other properties of function instances; 'arguments', 'caller'. */

			DUK_DDPRINT("built-in object %d, function property %d -> %!T", i, j, duk_get_tval(ctx, -1));

			/* [ (builtin objects) func ] */

			/*
			 *  The default property attributes are correct for all
			 *  function valued properties of built-in objects now.
			 */

			duk_def_prop_stridx(ctx, i, stridx, DUK_PROPDESC_FLAGS_WC);

			/* [ (builtin objects) ] */
		}
	}

	/*
	 *  Special post-tweaks, for cases not covered by the init data format.
	 *
	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
	 *    toGMTString is required to have the same Function object as
	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
	 *    this, V8 does not (the Function objects are distinct).
	 *
	 *  - Make DoubleError non-extensible.
	 *
	 *  - Add info about most important effective compile options to Duktape.
	 */

	duk_get_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
	duk_def_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);

	h = duk_require_hobject(ctx, DUK_BIDX_DOUBLE_ERROR);
	DUK_ASSERT(h != NULL);
	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);

	duk_push_string(ctx,
#if defined(DUK_USE_INTEGER_LE)
	                "l"
#elif defined(DUK_USE_INTEGER_BE)
	                "b"
#elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
	                "m"
#else
	                "?"
#endif
#if defined(DUK_USE_DOUBLE_LE)
	                "l"
#elif defined(DUK_USE_DOUBLE_BE)
	                "b"
#elif defined(DUK_USE_DOUBLE_ME)
	                "m"
#else
	                "?"
#endif
#if defined(DUK_USE_BYTEORDER_FORCED)
			"f"
#endif
	                " "
#if defined(DUK_USE_PACKED_TVAL)
	                "p"
#else
	                "u"
#endif
	                " "
#if defined(DUK_USE_HOBJECT_LAYOUT_1)
			"p1"
#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
			"p2"
#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
			"p3"
#else
			"p?"
#endif
			" "
#if defined(DUK_USE_ALIGN_4)
			"a4"
#elif defined(DUK_USE_ALIGN_8)
			"a8"
#else
			"a1"
#endif
			" "
	                DUK_USE_ARCH_STRING);
	duk_def_prop_stridx(ctx, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);

	/*
	 *  InitJS code - Ecmascript code evaluated from a built-in source
	 *  which provides e.g. backward compatibility.  User can also provide
	 *  JS code to be evaluated at startup.
	 */

#ifdef DUK_USE_INITJS
	/* FIXME: compression */
	duk_eval_string(ctx, (const char *) duk_initjs_data);  /* initjs data is NUL terminated */
	duk_pop(ctx);
#endif  /* DUK_USE_INITJS */

#ifdef DUK_USE_USER_INITJS
	/* FIXME: compression, at least as an option? */
	/* FIXME: unused now */
	duk_eval_string(ctx, (const char *) DUK_USE_USER_INITJS);
	duk_pop(ctx);
#endif  /* DUK_USE_USER_INITJS */

	/*
	 *  Since built-ins are not often extended, compact them.
	 */

	DUK_DDPRINT("compact built-ins");
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		duk_hobject_compact_props(thr, thr->builtins[i]);
	}

	DUK_DPRINT("INITBUILTINS END");

#ifdef DUK_USE_DDEBUG
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		DUK_DDPRINT("built-in object %d after initialization and compacting: %!@iO", i, thr->builtins[i]);
	}
#endif
	
#ifdef DUK_USE_DDDEBUG
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		DUK_DDDPRINT("built-in object %d after initialization and compacting", i);
		DUK_DEBUG_DUMP_HOBJECT(thr->builtins[i]);
	}
#endif

	/*
	 *  Pop built-ins from stack: they are now INCREF'd and
	 *  reachable from the builtins[] array.
	 */

	duk_pop_n(ctx, DUK_NUM_BUILTINS);
	DUK_ASSERT_TOP(ctx, 0);
}
Beispiel #18
0
static int duk__traceback_getter_helper(duk_context *ctx, int output_type) {
	duk_hthread *thr = (duk_hthread *) ctx;
	int idx_td;
	int i;
	const char *str_tailcalled = " tailcalled";
	const char *str_strict = " strict";
	const char *str_construct = " construct";
	const char *str_prevyield = " preventsyield";
	const char *str_directeval = " directeval";
	const char *str_empty = "";

	DUK_ASSERT_TOP(ctx, 0);  /* fixed arg count */

	duk_push_this(ctx);
	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TRACEDATA);
	idx_td = duk_get_top_index(ctx);

	duk_push_hstring_stridx(ctx, DUK_STRIDX_NEWLINE_TAB);
	duk_push_this(ctx);
	duk_to_string(ctx, -1);

	/* [ ... this tracedata sep ToString(this) ] */

	/* FIXME: skip null filename? */

	if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) {
		int t;

		/* Current tracedata contains 2 entries per callstack entry. */
		for (i = 0; ; i += 2) {
			int pc;
			int line;
			int flags;
			double d;
			const char *funcname;
			duk_hobject *h_func;
			duk_hstring *h_name;
			duk_hbuffer_fixed *pc2line;

			duk_require_stack(ctx, 5);
			duk_get_prop_index(ctx, idx_td, i);
			duk_get_prop_index(ctx, idx_td, i + 1);
			d = duk_to_number(ctx, -1);
			pc = (int) fmod(d, DUK_DOUBLE_2TO32);
			flags = (int) floor(d / DUK_DOUBLE_2TO32);
			t = duk_get_type(ctx, -2);

			if (t == DUK_TYPE_OBJECT) {
				/*
				 *  Ecmascript/native function call
				 */

				/* [ ... v1(func) v2(pc+flags) ] */

				h_func = duk_get_hobject(ctx, -2);
				DUK_ASSERT(h_func != NULL);

				duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
				duk_get_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME);

				duk_get_prop_stridx(ctx, -4, DUK_STRIDX_INT_PC2LINE);
				if (duk_is_buffer(ctx, -1)) {
					pc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
					DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line));
					line = duk_hobject_pc2line_query(pc2line, (duk_uint_fast32_t) pc);
				} else {
					line = 0;
				}
				duk_pop(ctx);

				/* [ ... v1 v2 name filename ] */

				if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
					return 1;
				} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
					duk_push_int(ctx, line);
					return 1;
				}

				h_name = duk_get_hstring(ctx, -2);  /* may be NULL */
				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
				           "anon" : (const char *) DUK_HSTRING_GET_DATA(h_name);
				if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h_func)) {
					duk_push_sprintf(ctx, "%s %s native%s%s%s%s%s",
					                 funcname,
					                 duk_get_string(ctx, -1),
					                 (flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty,
					                 (flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcalled : str_empty,
					                 (flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty,
					                 (flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty,
					                 (flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty);

				} else {
					duk_push_sprintf(ctx, "%s %s:%d%s%s%s%s%s",
					                 funcname,
					                 duk_get_string(ctx, -1),
					                 line,
					                 (flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty,
					                 (flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcalled : str_empty,
					                 (flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty,
					                 (flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty,
					                 (flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty);
				}
				duk_replace(ctx, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
				duk_pop_n(ctx, 3);      /* -> [ ... str ] */
			} else if (t == DUK_TYPE_STRING) {
				/*
				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
				 *  the error (fileName, lineNumber), sometimes not.
				 */

				/* [ ... v1(filename) v2(line+flags) ] */

				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
						duk_pop(ctx);
						return 1;
					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
						duk_push_int(ctx, pc);
						return 1;
					}
				}

				duk_push_sprintf(ctx, "%s:%d",
				                 duk_get_string(ctx, -2), pc);
				duk_replace(ctx, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
				duk_pop(ctx);          /* -> [ ... str ] */
			} else {
				/* unknown, ignore */
				duk_pop_2(ctx);
				break;
			}
		}

		if (i >= DUK_USE_TRACEBACK_DEPTH * 2) {
			/* Possibly truncated; there is no explicit truncation
			 * marker so this is the best we can do.
			 */

			duk_push_hstring_stridx(ctx, DUK_STRIDX_BRACKETED_ELLIPSIS);
		}
	}

	/* [ ... this tracedata sep ToString(this) str1 ... strN ] */

	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
		return 0;
	} else {
		duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/);
		return 1;
	}
}
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;
}
Beispiel #20
0
DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_context *ctx, duk_small_int_t output_type) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_idx_t idx_td;
	duk_small_int_t i;  /* traceback depth fits into 16 bits */
	duk_small_int_t t;  /* stack type fits into 16 bits */
	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
	const char *str_tailcall = " tailcall";
	const char *str_strict = " strict";
	const char *str_construct = " construct";
	const char *str_prevyield = " preventsyield";
	const char *str_directeval = " directeval";
	const char *str_empty = "";

	DUK_ASSERT_TOP(ctx, 0);  /* fixed arg count */
	DUK_UNREF(thr);

	duk_push_this(ctx);
	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TRACEDATA);
	idx_td = duk_get_top_index(ctx);

	duk_push_hstring_stridx(ctx, DUK_STRIDX_NEWLINE_4SPACE);
	duk_push_this(ctx);

	/* [ ... this tracedata sep this ] */

	/* XXX: skip null filename? */

	if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) {
		/* Current tracedata contains 2 entries per callstack entry. */
		for (i = 0; ; i += 2) {
			duk_int_t pc;
			duk_int_t line;
			duk_int_t flags;
			duk_double_t d;
			const char *funcname;
			const char *filename;
			duk_hobject *h_func;
			duk_hstring *h_name;

			duk_require_stack(ctx, 5);
			duk_get_prop_index(ctx, idx_td, i);
			duk_get_prop_index(ctx, idx_td, i + 1);
			d = duk_to_number(ctx, -1);
			pc = (duk_int_t) DUK_FMOD(d, DUK_DOUBLE_2TO32);
			flags = (duk_int_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);
			t = (duk_small_int_t) duk_get_type(ctx, -2);

			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
				/*
				 *  Ecmascript/native function call or lightfunc call
				 */

				count_func++;

				/* [ ... v1(func) v2(pc+flags) ] */

				h_func = duk_get_hobject(ctx, -2);  /* NULL for lightfunc */

				duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
				duk_get_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME);

#if defined(DUK_USE_PC2LINE)
				line = duk_hobject_pc2line_query(ctx, -4, (duk_uint_fast32_t) pc);
#else
				line = 0;
#endif

				/* [ ... v1 v2 name filename ] */

				/* When looking for .fileName/.lineNumber, blame first
				 * function which has a .fileName.
				 */
				if (duk_is_string(ctx, -1)) {
					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
						return 1;
					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
						duk_push_int(ctx, line);
						return 1;
					}
				}

				/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
				/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
				h_name = duk_get_hstring(ctx, -2);  /* may be NULL */
				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
				           "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
				filename = duk_get_string(ctx, -1);
				filename = filename ? filename : "";
				DUK_ASSERT(funcname != NULL);
				DUK_ASSERT(filename != NULL);

				if (h_func == NULL) {
					duk_push_sprintf(ctx, "at %s light%s%s%s%s%s",
					                 (const char *) funcname,
					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
				} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
					duk_push_sprintf(ctx, "at %s (%s) native%s%s%s%s%s",
					                 (const char *) funcname,
					                 (const char *) filename,
					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
				} else {
					duk_push_sprintf(ctx, "at %s (%s:%ld)%s%s%s%s%s",
					                 (const char *) funcname,
					                 (const char *) filename,
					                 (long) line,
					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
				}
				duk_replace(ctx, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
				duk_pop_n(ctx, 3);      /* -> [ ... str ] */
			} else if (t == DUK_TYPE_STRING) {
				/*
				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
				 *  the error (fileName, lineNumber), sometimes not.
				 */

				/* [ ... v1(filename) v2(line+flags) ] */

				/* When looking for .fileName/.lineNumber, blame compilation
				 * or C call site unless flagged not to do so.
				 */
				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
						duk_pop(ctx);
						return 1;
					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
						duk_push_int(ctx, pc);
						return 1;
					}
				}

				duk_push_sprintf(ctx, "at [anon] (%s:%ld) internal",
				                 (const char *) duk_get_string(ctx, -2), (long) pc);
				duk_replace(ctx, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
				duk_pop(ctx);          /* -> [ ... str ] */
			} else {
				/* unknown, ignore */
				duk_pop_2(ctx);
				break;
			}
		}

		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
			/* Possibly truncated; there is no explicit truncation
			 * marker so this is the best we can do.
			 */

			duk_push_hstring_stridx(ctx, DUK_STRIDX_BRACKETED_ELLIPSIS);
		}
	}

	/* [ ... this tracedata sep this str1 ... strN ] */

	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
		return 0;
	} else {
		/* The 'this' after 'sep' will get ToString() coerced by
		 * duk_join() automatically.  We don't want to do that
		 * coercion when providing .fileName or .lineNumber (GH-254).
		 */
		duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/);
		return 1;
	}
}
AJ_Status AJS_FoundAdvertisedName(duk_context* ctx, AJ_Message* msg)
{
    AJ_Status status;
    SessionInfo* sessionInfo;
    const char* name;
    const char* prefix;
    uint16_t port;
    uint16_t mask;
    duk_idx_t fnmeIdx;
    duk_idx_t sessIdx;

    AJ_UnmarshalArgs(msg, "sqs", &name, &mask, &prefix);

    AJ_InfoPrintf(("AJS_FoundAdvertisedName %s %s\n", prefix, name));

    AJS_GetGlobalStashObject(ctx, "sessions");
    sessIdx = duk_get_top_index(ctx);
    /*
     * If the name is already listed we can ignore this signal
     */
    if (duk_get_prop_string(ctx, -1, name)) {
        duk_pop_2(ctx);
        return AJ_OK;
    }
    /*
     * Check if there is a callback registered for this name (actually the prefix)
     */
    AJS_GetGlobalStashObject(ctx, "findName");
    duk_get_prop_string(ctx, -1, prefix);
    if (duk_is_undefined(ctx, -1)) {
        duk_pop_3(ctx);
        return AJ_OK;
    }
    fnmeIdx = duk_get_top_index(ctx);
    /*
     * From here on we make it look like we received an announcement
     */
    port = AJS_GetIntProp(ctx, fnmeIdx, "port");
    status = AJ_BusJoinSession(msg->bus, name, port, NULL);
    if (status == AJ_OK) {
        duk_idx_t anIdx;
        duk_idx_t svcIdx;
        /*
         * Create service object and add it to the sessions array
         */
        svcIdx = duk_push_object(ctx);
        /*
         * Set the "info" and "anno" properties on the service object
         */
        sessionInfo = duk_push_fixed_buffer(ctx, sizeof(SessionInfo));
        sessionInfo->port = port;
        duk_put_prop_string(ctx, svcIdx, "info");
        anIdx = duk_push_array(ctx);
        /*
         * Push array of interfaces
         */
        duk_get_prop_string(ctx, fnmeIdx, "interfaces");
        /*
         * Set the callback to be called when the JOIN_SESSION reply is received
         */
        AJS_GetGlobalStashObject(ctx, "serviceCB");
        duk_get_prop_index(ctx, -2, 0);           /* key - first interface in "interfaces" array */
        duk_get_prop_string(ctx, fnmeIdx, "cb");  /* val - callback function */
        duk_put_prop(ctx, -3);
        duk_pop(ctx);
        /* Interfaces array is at the top of the stack */
        AddServiceObject(ctx, sessionInfo, AJS_GetStringProp(ctx, fnmeIdx, "path"), name);
        /*
         * Append service object to the announcements array for processing later
         */
        duk_put_prop_index(ctx, anIdx, duk_get_length(ctx, anIdx));

        AJ_ASSERT(duk_get_top_index(ctx) == anIdx);
        duk_put_prop_string(ctx, svcIdx, "anno");
        AJ_ASSERT(duk_get_top_index(ctx) == svcIdx);
        duk_put_prop_string(ctx, sessIdx, name);
        /*
         * Store the reply serial number for the JOIN_SESSION reply
         */
        sessionInfo->replySerial = msg->bus->serial - 1;
    } else {
        duk_del_prop_string(ctx, sessIdx, prefix);
    }
    /* Clean up the stack */
    duk_pop_n(ctx, 4);
    return status;
}
DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
	duk_context *ctx = (duk_context *) thr;
	duk_bitdecoder_ctx bd_ctx;
	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
	duk_hobject *h;
	duk_small_uint_t i, j;

	DUK_D(DUK_DPRINT("INITBUILTINS BEGIN"));

	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
	bd->data = (const duk_uint8_t *) duk_builtins_data;
	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;

	/*
	 *  First create all built-in bare objects on the empty valstack.
	 *  During init, their indices will correspond to built-in indices.
	 *
	 *  Built-ins will be reachable from both valstack and thr->builtins.
	 */

	/* XXX: there is no need to resize valstack because builtin count
	 * is much less than the default space; assert for it.
	 */

	DUK_DD(DUK_DDPRINT("create empty built-ins"));
	DUK_ASSERT_TOP(ctx, 0);
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		duk_small_uint_t class_num;
		duk_small_int_t len = -1;  /* must be signed */

		class_num = (duk_small_uint_t) duk_bd_decode(bd, DUK__CLASS_BITS);
		len = (duk_small_int_t) duk_bd_decode_flagged(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);

		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
			duk_small_uint_t natidx;
			duk_small_uint_t stridx;
			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
			duk_c_function c_func;
			duk_int16_t magic;

			DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
			DUK_ASSERT(len >= 0);

			natidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);
			stridx = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS);
			c_func = duk_bi_native_functions[natidx];

			c_nargs = (duk_small_uint_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, len /*def_value*/);
			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
				c_nargs = DUK_VARARGS;
			}

			/* XXX: set magic directly here? (it could share the c_nargs arg) */
			duk_push_c_function_noexotic(ctx, c_func, c_nargs);

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

			/* Currently all built-in native functions are strict.
			 * duk_push_c_function() now sets strict flag, so
			 * assert for it.
			 */
			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));

			/* XXX: function properties */

			duk_push_hstring_stridx(ctx, stridx);
			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);

			/* Almost all global level Function objects are constructable
			 * but not all: Function.prototype is a non-constructable,
			 * callable Function.
			 */
			if (duk_bd_decode_flag(bd)) {
				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
			} else {
				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
			}

			/* Cast converts magic to 16-bit signed value */
			magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0 /*def_value*/);
			((duk_hnativefunction *) h)->magic = magic;
		} else {
			/* XXX: ARRAY_PART for Array prototype? */

			duk_push_object_helper(ctx,
			                       DUK_HOBJECT_FLAG_EXTENSIBLE,
			                       -1);  /* no prototype or class yet */

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

		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);

		thr->builtins[i] = h;
		DUK_HOBJECT_INCREF(thr, &h->hdr);

		if (len >= 0) {
			/*
			 *  For top-level objects, 'length' property has the following
			 *  default attributes: non-writable, non-enumerable, non-configurable
			 *  (E5 Section 15).
			 *
			 *  However, 'length' property for Array.prototype has attributes
			 *  expected of an Array instance which are different: writable,
			 *  non-enumerable, non-configurable (E5 Section 15.4.5.2).
			 *
			 *  This is currently determined implicitly based on class; there are
			 *  no attribute flags in the init data.
			 */

			duk_push_int(ctx, len);
			duk_xdef_prop_stridx(ctx,
			                     -2,
			                     DUK_STRIDX_LENGTH,
			                     (class_num == DUK_HOBJECT_CLASS_ARRAY ?  /* only Array.prototype matches */
			                      DUK_PROPDESC_FLAGS_W : DUK_PROPDESC_FLAGS_NONE));
		}

		/* enable exotic behaviors last */

		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
			DUK_HOBJECT_SET_EXOTIC_ARRAY(h);
		}
		if (class_num == DUK_HOBJECT_CLASS_STRING) {
			DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
		}

		/* some assertions */

		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPILEDFUNCTION(h));
		/* DUK_HOBJECT_FLAG_NATIVEFUNCTION varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h));       /* currently, even for Array.prototype */
		/* DUK_HOBJECT_FLAG_STRICT varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(h) ||  /* all native functions have NEWENV */
		           DUK_HOBJECT_HAS_NEWENV(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_ENVRECCLOSED(h));
		/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
		/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));

		DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
	}

	/*
	 *  Then decode the builtins init data (see genbuiltins.py) to
	 *  init objects
	 */

	DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		duk_small_uint_t t;
		duk_small_uint_t num;

		DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
		h = thr->builtins[i];

		t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
		if (t != DUK__NO_BIDX_MARKER) {
			DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[t]);
		}

		t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
		if (t != DUK__NO_BIDX_MARKER) {
			/* 'prototype' property for all built-in objects (which have it) has attributes:
			 *  [[Writable]] = false,
			 *  [[Enumerable]] = false,
			 *  [[Configurable]] = false
			 */
			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
			duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_PROTOTYPE, t, DUK_PROPDESC_FLAGS_NONE);
		}

		t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
		if (t != DUK__NO_BIDX_MARKER) {
			/* 'constructor' property for all built-in objects (which have it) has attributes:
			 *  [[Writable]] = true,
			 *  [[Enumerable]] = false,
			 *  [[Configurable]] = true
			 */
			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
			duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_CONSTRUCTOR, t, DUK_PROPDESC_FLAGS_WC);
		}

		/* normal valued properties */
		num = (duk_small_uint_t) duk_bd_decode(bd, DUK__NUM_NORMAL_PROPS_BITS);
		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
		for (j = 0; j < num; j++) {
			duk_small_uint_t stridx;
			duk_small_uint_t prop_flags;

			stridx = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS);

			/*
			 *  Property attribute defaults are defined in E5 Section 15 (first
			 *  few pages); there is a default for all properties and a special
			 *  default for 'length' properties.  Variation from the defaults is
			 *  signaled using a single flag bit in the bitstream.
			 */

			if (duk_bd_decode_flag(bd)) {
				prop_flags = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_FLAGS_BITS);
			} else {
				if (stridx == DUK_STRIDX_LENGTH) {
					prop_flags = DUK_PROPDESC_FLAGS_NONE;
				} else {
					prop_flags = DUK_PROPDESC_FLAGS_WC;
				}
			}

			t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);

			DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, stridx %ld, flags 0x%02lx, type %ld",
			                     (long) i, (long) j, (long) stridx, (unsigned long) prop_flags, (long) t));

			switch (t) {
			case DUK__PROP_TYPE_DOUBLE: {
				duk_double_union du;
				duk_small_uint_t k;

				for (k = 0; k < 8; k++) {
					/* Encoding endianness must match target memory layout,
					 * build scripts and genbuiltins.py must ensure this.
					 */
					du.uc[k] = (duk_uint8_t) duk_bd_decode(bd, 8);
				}

				duk_push_number(ctx, du.d);  /* push operation normalizes NaNs */
				break;
			}
			case DUK__PROP_TYPE_STRING: {
				duk_small_uint_t n;
				duk_small_uint_t k;
				duk_uint8_t *p;

				n = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRING_LENGTH_BITS);
				p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, n);
				for (k = 0; k < n; k++) {
					*p++ = (duk_uint8_t) duk_bd_decode(bd, DUK__STRING_CHAR_BITS);
				}

				duk_to_string(ctx, -1);
				break;
			}
			case DUK__PROP_TYPE_STRIDX: {
				duk_small_uint_t n;

				n = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS);
				DUK_ASSERT_DISABLE(n >= 0);  /* unsigned */
				DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
				duk_push_hstring_stridx(ctx, n);
				break;
			}
			case DUK__PROP_TYPE_BUILTIN: {
				duk_small_uint_t bidx;

				bidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
				DUK_ASSERT(bidx != DUK__NO_BIDX_MARKER);
				duk_dup(ctx, (duk_idx_t) bidx);
				break;
			}
			case DUK__PROP_TYPE_UNDEFINED: {
				duk_push_undefined(ctx);
				break;
			}
			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
				duk_push_true(ctx);
				break;
			}
			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
				duk_push_false(ctx);
				break;
			}
			case DUK__PROP_TYPE_ACCESSOR: {
				duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);
				duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);
				duk_c_function c_func_getter;
				duk_c_function c_func_setter;

				/* XXX: this is a bit awkward because there is no exposed helper
				 * in the API style, only this internal helper.
				 */
				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, stridx=%ld, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
				                     (long) i, (long) stridx, (long) natidx_getter, (long) natidx_setter, (unsigned long) prop_flags));

				c_func_getter = duk_bi_native_functions[natidx_getter];
				c_func_setter = duk_bi_native_functions[natidx_setter];
				duk_push_c_function_noconstruct_noexotic(ctx, c_func_getter, 0);  /* always 0 args */
				duk_push_c_function_noconstruct_noexotic(ctx, c_func_setter, 1);  /* always 1 arg */

				/* XXX: magic for getter/setter? */

				prop_flags |= DUK_PROPDESC_FLAG_ACCESSOR;  /* accessor flag not encoded explicitly */
				duk_hobject_define_accessor_internal(thr,
				                                     duk_require_hobject(ctx, i),
				                                     DUK_HTHREAD_GET_STRING(thr, stridx),
				                                     duk_require_hobject(ctx, -2),
				                                     duk_require_hobject(ctx, -1),
				                                     prop_flags);
				duk_pop_2(ctx);  /* getter and setter, now reachable through object */
				goto skip_value;
			}
			default: {
				/* exhaustive */
				DUK_UNREACHABLE();
			}
			}

			DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0);
			duk_xdef_prop_stridx(ctx, i, stridx, prop_flags);

		 skip_value:
			continue;  /* avoid empty label at the end of a compound statement */
		}

		/* native function properties */
		num = (duk_small_uint_t) duk_bd_decode(bd, DUK__NUM_FUNC_PROPS_BITS);
		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
		for (j = 0; j < num; j++) {
			duk_small_uint_t stridx;
			duk_small_uint_t natidx;
			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
			duk_small_uint_t c_length;
			duk_int16_t magic;
			duk_c_function c_func;
			duk_hnativefunction *h_func;
#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
			duk_small_int_t lightfunc_eligible;
#endif

			stridx = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS);
			natidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);

			c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
			c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_int32_t) c_length /*def_value*/);
			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
				c_nargs = DUK_VARARGS;
			}

			c_func = duk_bi_native_functions[natidx];

			DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, stridx %ld, natidx %ld, length %ld, nargs %ld",
			                     (long) i, (long) j, (long) stridx, (long) natidx, (long) c_length,
			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));

			/* Cast converts magic to 16-bit signed value */
			magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0);

#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
			lightfunc_eligible =
				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
			if (stridx == DUK_STRIDX_EVAL ||
			    stridx == DUK_STRIDX_YIELD ||
			    stridx == DUK_STRIDX_RESUME ||
			    stridx == DUK_STRIDX_REQUIRE) {
				/* These functions have trouble working as lightfuncs.
				 * Some of them have specific asserts and some may have
			         * additional properties (e.g. 'require.id' may be written).
				 */
				DUK_D(DUK_DPRINT("reject as lightfunc: stridx=%d, i=%d, j=%d", (int) stridx, (int) i, (int) j));
				lightfunc_eligible = 0;
			}

			if (lightfunc_eligible) {
				duk_tval tv_lfunc;
				duk_small_uint_t lf_nargs = (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
				duk_push_tval(ctx, &tv_lfunc);
				DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld -> %!iT", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic, duk_get_tval(ctx, -1)));
				goto lightfunc_skip;
			}

			DUK_D(DUK_DPRINT("built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic));
#endif  /* DUK_USE_LIGHTFUNC_BUILTINS */

			/* [ (builtin objects) ] */

			duk_push_c_function_noconstruct_noexotic(ctx, c_func, c_nargs);
			h_func = duk_require_hnativefunction(ctx, -1);
			DUK_UNREF(h_func);

			/* Currently all built-in native functions are strict.
			 * This doesn't matter for many functions, but e.g.
			 * String.prototype.charAt (and other string functions)
			 * rely on being strict so that their 'this' binding is
			 * not automatically coerced.
			 */
			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);

			/* No built-in functions are constructable except the top
			 * level ones (Number, etc).
			 */
			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));

			/* XXX: any way to avoid decoding magic bit; there are quite
			 * many function properties and relatively few with magic values.
			 */
			h_func->magic = magic;

			/* [ (builtin objects) func ] */

			duk_push_int(ctx, c_length);
			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);

			duk_push_hstring_stridx(ctx, stridx);
			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);

			/* XXX: other properties of function instances; 'arguments', 'caller'. */

			DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
			                   (long) i, (long) j, (duk_tval *) duk_get_tval(ctx, -1)));

			/* [ (builtin objects) func ] */

			/*
			 *  The default property attributes are correct for all
			 *  function valued properties of built-in objects now.
			 */

#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
		 lightfunc_skip:
#endif

			duk_xdef_prop_stridx(ctx, i, stridx, DUK_PROPDESC_FLAGS_WC);

			/* [ (builtin objects) ] */
		}
	}

	/*
	 *  Special post-tweaks, for cases not covered by the init data format.
	 *
	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
	 *    toGMTString is required to have the same Function object as
	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
	 *    this, V8 does not (the Function objects are distinct).
	 *
	 *  - Make DoubleError non-extensible.
	 *
	 *  - Add info about most important effective compile options to Duktape.
	 *
	 *  - Possibly remove some properties (values or methods) which are not
	 *    desirable with current feature options but are not currently
	 *    conditional in init data.
	 */

	duk_get_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
	duk_xdef_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);

	h = duk_require_hobject(ctx, DUK_BIDX_DOUBLE_ERROR);
	DUK_ASSERT(h != NULL);
	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);

#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
#endif

#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
#endif

	duk_push_string(ctx,
			/* Endianness indicator */
#if defined(DUK_USE_INTEGER_LE)
	                "l"
#elif defined(DUK_USE_INTEGER_BE)
	                "b"
#elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
	                "m"
#else
	                "?"
#endif
#if defined(DUK_USE_DOUBLE_LE)
	                "l"
#elif defined(DUK_USE_DOUBLE_BE)
	                "b"
#elif defined(DUK_USE_DOUBLE_ME)
	                "m"
#else
	                "?"
#endif
#if defined(DUK_USE_BYTEORDER_FORCED)
			"f"
#endif
	                " "
			/* Packed or unpacked tval */
#if defined(DUK_USE_PACKED_TVAL)
	                "p"
#else
	                "u"
#endif
#if defined(DUK_USE_FASTINT)
			"f"
#endif
			" "
			/* Low memory options */
#if defined(DUK_USE_STRTAB_CHAIN)
			"c"  /* chain */
#elif defined(DUK_USE_STRTAB_PROBE)
			"p"  /* probe */
#else
			"?"
#endif
#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
			"n"
#endif
#if defined(DUK_USE_HEAPPTR16)
			"h"
#endif
#if defined(DUK_USE_DATAPTR16)
			"d"
#endif
#if defined(DUK_USE_FUNCPTR16)
			"f"
#endif
#if defined(DUK_USE_REFCOUNT16)
			"R"
#endif
#if defined(DUK_USE_STRHASH16)
			"H"
#endif
#if defined(DUK_USE_STRLEN16)
			"S"
#endif
#if defined(DUK_USE_BUFLEN16)
			"B"
#endif
#if defined(DUK_USE_OBJSIZES16)
			"O"
#endif
#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
			"L"
#endif
	                " "
			/* Object property allocation layout */
#if defined(DUK_USE_HOBJECT_LAYOUT_1)
			"p1"
#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
			"p2"
#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
			"p3"
#else
			"p?"
#endif
			" "
			/* Alignment guarantee */
#if defined(DUK_USE_ALIGN_4)
			"a4"
#elif defined(DUK_USE_ALIGN_8)
			"a8"
#else
			"a1"
#endif
			" "
			/* Architecture, OS, and compiler strings */
	                DUK_USE_ARCH_STRING
			" "
	                DUK_USE_OS_STRING
			" "
	                DUK_USE_COMPILER_STRING);
	duk_xdef_prop_stridx(ctx, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);

	/*
	 *  InitJS code - Ecmascript code evaluated from a built-in source
	 *  which provides e.g. backward compatibility.  User can also provide
	 *  JS code to be evaluated at startup.
	 */

#ifdef DUK_USE_BUILTIN_INITJS
	/* XXX: compression */
	DUK_DD(DUK_DDPRINT("running built-in initjs"));
	duk_eval_string(ctx, (const char *) duk_initjs_data);  /* initjs data is NUL terminated */
	duk_pop(ctx);
#endif  /* DUK_USE_BUILTIN_INITJS */

#ifdef DUK_USE_USER_INITJS
	/* XXX: compression (as an option) */
	DUK_DD(DUK_DDPRINT("running user initjs"));
	duk_eval_string_noresult(ctx, (const char *) DUK_USE_USER_INITJS);
#endif  /* DUK_USE_USER_INITJS */

	/*
	 *  Since built-ins are not often extended, compact them.
	 */

	DUK_DD(DUK_DDPRINT("compact built-ins"));
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		duk_hobject_compact_props(thr, thr->builtins[i]);
	}

	DUK_D(DUK_DPRINT("INITBUILTINS END"));

#ifdef DUK_USE_DDPRINT
	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
		                   (long) i, (duk_heaphdr *) thr->builtins[i]));
	}
#endif

	/*
	 *  Pop built-ins from stack: they are now INCREF'd and
	 *  reachable from the builtins[] array.
	 */

	duk_pop_n(ctx, DUK_NUM_BUILTINS);
	DUK_ASSERT_TOP(ctx, 0);
}
//void duk_pop_n(duk_context *ctx, duk_idx_t count);
void aperl_duk_pop_n(duk_context *ctx, duk_idx_t count) {
	duk_pop_n(ctx, count);
}
Beispiel #24
0
void Context::pop(index_t count)
{
    duk_pop_n(m_handle, count);
}