Skip to content

instanceof operator doesn't work for objects exposed to JS #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
5 tasks done
arekdygas opened this issue Mar 25, 2025 · 1 comment
Open
5 tasks done

instanceof operator doesn't work for objects exposed to JS #103

arekdygas opened this issue Mar 25, 2025 · 1 comment
Labels

Comments

@arekdygas
Copy link
Contributor

arekdygas commented Mar 25, 2025

Bug Report

Prerequisites

  • Can you reproduce the problem in a MWE?
  • Are you running the latest version of AngleSharp?
  • Did you check the FAQs to see if that helps you?
  • Are you reporting to the correct repository? (there are multiple AngleSharp libraries, e.g., AngleSharp.Css for CSS support)
  • Did you perform a search in the issues?

For more information, see the CONTRIBUTING guide.

Description

As title says - instanceof operator doesn't work e.g. for Window, Element, etc.

Steps to Reproduce

var config = Configuration.Default.WithJs();
var context = BrowsingContext.New(config);
var document = await context.OpenAsync(req => req.Content("")).ConfigureAwait(false);
Console.WriteLine(document.ExecuteScript("window instanceof Window"));
Console.WriteLine(document.ExecuteScript("document.createElement('div') instanceof Element"));

Expected behavior:

Console output: twice True

Actual behavior:

Console output: twice False

Environment details:

.NET Framework 4.8, Win 10

Possible Solution

I have to admit here, that I'm not sure how to fix it properly. Simple fix, which works in my case, is quite easy and includes adding [Symbol.hasInstance] implementation to DomConstructorInstance, but I have no idea if this a correct way, and even if it is, then if my implementation would not fail for some cases.

My solution

In DomConstructorInstance constructor, the following code was added

var hasInstanceFunction = new ClrFunction(Engine, "[Symbol.hasInstance]", (thisObj, args) => IsInstanceOf(args[0], type), 1, PropertyFlag.None);
var hasInstanceProperty = new PropertyDescriptor(hasInstanceFunction, false, false, false);
FastSetProperty(Jint.Native.Symbol.GlobalSymbolRegistry.HasInstance, hasInstanceProperty);

EDIT: changed PropertyFlag.Configurable to PropertyFlag.None

And IsInstance method:

private JsValue IsInstanceOf(JsValue arg, Type type)
{
    return type.IsInstanceOfType(arg.ToObject());
}
@arekdygas arekdygas added the bug label Mar 25, 2025
@arekdygas
Copy link
Contributor Author

I investigated it a bit more, and it looks like the issue is related to prototype chains. My initial solution, while working for my case, is not a good one.

There are 2 problems I currently see in DomPrototypeInstance constructor:

  1. When BaseType is null, prototype is set to Object and I think it should be set to FunctionPrototype. Jint uses for this _realm.Intrinsics.Function.PrototypeObject, but I have no idea if this is the correct method for handling this in AngleSharp.
  2. When DomPrototypeInstance is created for interface, concept of BaseType fails. For example, HTMLDivElement prototype is Object (due to p. 1) and should be HTMLElement. Fixing this would probably require analyze of implemented interfaces hierarchy and attaching the "top one" as a prototype.

I'll try to look into it in a couple of days, but some hints are welcome, especially to p.1 ;)

And btw - Happy Easter!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant