AngleSharp / AngleSharp.Css

:angel: Library to enable support for cascading stylesheets in AngleSharp.

Home Page:https://anglesharp.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Null reference exception with GetComputedStyle when the source is a string

Tony20221 opened this issue · comments

I have this code which runs fine.

    var config = Configuration.Default.WithDefaultLoader().WithCss();
            //var context = BrowsingContext.New(Configuration.Default);
            var context = BrowsingContext.New(config);

//            var document = context.OpenAsync(req => req.Content(html)).Result;
         var document = context.OpenAsync("https://www.google.com").Result;

            var element = document.All.Where(m => m.LocalName == "input" && m.HasAttribute("value") && !string.IsNullOrEmpty(m.GetAttribute("value"))).First();
            var style = document.DefaultView.GetComputedStyle(element);

When I switch the code to use the 'html' variable instead of opening the Google web page, I get a null object reference exception in the line with GetComputedStyle method. document and DefaultView and element are not null.
The variable 'html' is a string which contains the html of the page after it has been rendered.

What am I missing?

This is the stack trace:
"Object reference not set to an instance of an object."
at AngleSharp.Css.FeatureValidators.WidthFeatureValidator.Validate(IMediaFeature feature, IRenderDevice renderDevice)
at AngleSharp.Css.Dom.MediaListExtensions.Validate(IMediaFeature feature, IRenderDevice device)
at AngleSharp.Css.Dom.MediaListExtensions.<>c__DisplayClass5_0.b__0(IMediaFeature m)
at System.Linq.Enumerable.Any[TSource](IEnumerable1 source, Func2 predicate)
at AngleSharp.Css.Dom.MediaListExtensions.Validate(ICssMedium medium, IRenderDevice device)
at AngleSharp.Css.Dom.MediaListExtensions.<>c__DisplayClass4_0.b__0(ICssMedium m)
at System.Linq.Enumerable.Any[TSource](IEnumerable1 source, Func2 predicate)
at AngleSharp.Css.Dom.MediaListExtensions.Validate(IMediaList list, IRenderDevice device)
at AngleSharp.Dom.StyleSheetExtensions.d__1.MoveNext()
at AngleSharp.Css.Dom.StyleCollection.d__5.MoveNext()
at System.Linq.Enumerable.WhereEnumerableIterator1.ToArray() at System.Linq.Buffer1..ctor(IEnumerable1 source) at System.Linq.OrderedEnumerable1.d__17.MoveNext()
at AngleSharp.Css.StyleCollectionExtensions.ComputeCascadedStyle(IEnumerable1 styleCollection, IElement element, ICssStyleDeclaration parent) at AngleSharp.Css.StyleCollectionExtensions.ComputeDeclarations(IEnumerable1 rules, IElement element, String pseudoSelector)
at AngleSharp.Dom.WindowExtensions.GetComputedStyle(IWindow window, IElement element, String pseudo)

Hm did you read the docs?

Furthermore, for some CSSOM features (e.g., media queries) a render device is required.

var config = Configuration.Default
    .WithCss()
    .WithRenderDevice(new DefaultRenderDevice
    {
        DeviceHeight = 768,
        DeviceWidth = 1024,
    });

Hope that helps!

(See https://github.com/AngleSharp/AngleSharp.Css#basic-configuration)

Well, where in the docs does it say that I need to use a render device when using a string vs opening a site? The docs says use a render device if using certain CSSOM features like when using media queries which I am not using.
You can add this fact in the docs to make it clear.

Anyway, thanks.

The docs says use a render device if using certain CSSOM features like when using media queries which I am not using.

like media queries, i.e., not only media queries. Calculating styles is a calculation (obviously) and therefore requires a render device.

You can add this fact in the docs to make it clear.

Sorry to phrase this - but you can also extend the docs (contributions welcome) + feel free to sponsor the project if the project saves you time.

Maybe there's a misunderstanding here. The code works fine when opening a webpage. It gives an exception when working directly with the html of a web page. I am not talking about what kind of css functionality is being used. I am just getting the style of an element. It's about the need for a rendering device when the input is a straight string but it's not needed when opening a web page. It seems in both cases the input is html. I mean when you request a webpage, you're getting back html from the web server. The fact that there's a clear distinction between how AngleSharp deals with the two cases is not evident in the docs.

I am new to AngleSharp and still learning. I don't have enough knowledge to contribute to any docs. Maybe in the future.

I am not talking about what kind of css functionality is being used. It's about the need for a rendering device when the input is a straight string but it's not needed when opening a web page

I may be confused here. Just to be straight. The exception is thrown because you did actually demand from AngleSharp to GetComputedStyle. The exception would not be thrown if you did not do that. Just parsing the DOM does not involve any style tree computations. Yes, CSS is parsed if its active - but parsing CSS is not the same as actively calculating styles (which would be necessary for the render tree).

I mean when you request a webpage, you're getting back html from the web server. The fact that there's a clear distinction between how AngleSharp deals with the two cases is not evident in the docs.

This is not what you are doing. You are already way beyond getting back HTML from somewhere. You are already dealing with the resulting DOM, which is (originally) based on this string, but not this string. It's a live model with an API in front - calling things on the API will trigger some functionality and when you want to trigger a style calculation the engine needs to have all the information to actually perform the calculation. Simple as that.

The only reason the exception was emitted in one case and not the other is that in one case there have been no CSS nodes that actually required no render device. This is as simple as: If you loop over nothing then nothing happens.