duktape icon indicating copy to clipboard operation
duktape copied to clipboard

How disable create class in JS code?

Open kirill-782 opened this issue 5 years ago • 6 comments

I reread a lot in the Wiki on the topic of banning the external constructor, but nowhere did I find C ++ code. Can I prevent the creation of an object from JS code? To give an error like in Chrome

new HTMLDocument ();
VM459: 1 Uncaught TypeError: Illegal constructor
     at <anonymous>: 1: 1

But so that there are no problems with creating an object in C ++ code

kirill-782 avatar Feb 27 '19 21:02 kirill-782

All Duktape/C functions are "constructable" from script point of view, but you can reject such calls explicitly using https://duktape.org/api.html#duk_is_constructor_call:

if (duk_is_constructor_call(ctx)) {
    duk_type_error(ctx, "not constructable");
}

svaarala avatar Feb 28 '19 14:02 svaarala

Internally each function actually does have a separate CONSTRUCTABLE flag, and there are some internally created functions which are not constructable. But the C check quoted above produces roughly the same result; there's a small difference in the traceback because the function is entered before the error is thrown. The ability to control the CONSTRUCTABLE flag or create a non-constructable function needs to be added to the API IMO.

svaarala avatar Feb 28 '19 15:02 svaarala

As for being able to create the instance from C code, you could use a structure such as this:

static void push_new_instance(duk_context *ctx) {
    /* Push and initialize instance; leave it on stack. */
    duk_push_object(ctx);

    /* ... */

    /* Finalize object's internal prototype, to inherit from what you want. */
    duk_eval_string(ctx, "HTMLDocument.prototype");  // push whatever object you want to inherit from
    duk_set_prototype(ctx, -2);

    /* If it matters, set .constructor property. It usually has little impact. */
    duk_eval_string(ctx, "HTMLDocument");
    duk_put_prop_string(ctx, -2, "prototype");
}

duk_ret_t my_function(duk_context *ctx) {
    if (duk_is_constructor_call(ctx)) {
        duk_type_error(ctx, "not constructable");
    }
    /* XXX: Do what you want with a non-constructor call. */
}

Any calls to the constructor via scripts (or even C code) would be rejected. But you'd be able to create instance with push_new_instance().

svaarala avatar Feb 28 '19 15:02 svaarala

Well, then there is still a small bug, or I don’t know, it can be so. When converting an object to a string, when no toString is specified, [object Object] is returned. Although the prototype object is different.

kirill-782 avatar Feb 28 '19 19:02 kirill-782

Could you try evaluating:

instance.toString === Object.prototype.toString

If this is true, then the inheritance chain (internal prototype) is still wrong.

You can also check what the prototype object is using:

Object.getPrototypeOf(instance)

and see which object that returns.

svaarala avatar Feb 28 '19 19:02 svaarala

@kirill-782 Any update on this?

svaarala avatar May 28 '19 17:05 svaarala