Skip to content

Conversation

@sleepy-monax
Copy link
Member

This rewrites the WebDriver in C++ to integrate it directly with the engine.
It now supports everything the previous implementations did. Plus PDF printing, retrieving the page source, and full session handling.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a complete WebDriver 2 protocol implementation in C++ directly integrated with the Vaev engine, replacing the previous implementation. The new implementation adds support for PDF printing, page source retrieval, and full session handling.

  • Adds new C++ WebDriver service with HTTP endpoints for the WebDriver 2 protocol
  • Implements core WebDriver functionality including sessions, navigation, window management, and screen capture
  • Adds HTML fragment serialization support for retrieving page source

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/vaev-webdriver/service.cpp Implements HTTP service endpoints for WebDriver 2 protocol (sessions, navigation, contexts, screenshots, printing)
src/vaev-webdriver/protocol.cpp Defines WebDriver protocol types and helper functions for success/error responses
src/vaev-webdriver/driver.cpp Core WebDriver logic handling sessions, windows, navigation, and document operations
src/vaev-webdriver/mod.cpp Module exports for the WebDriver implementation
src/vaev-webdriver/manifest.json Component manifest declaring vaev-engine dependency
src/vaev-webdriver/main/manifest.json Executable manifest for WebDriver server
src/vaev-webdriver/main/main.cpp Entry point for WebDriver server with CLI option parsing
src/vaev-engine/style/specified.cpp Changes opacity field from f16 to f32 for compatibility
src/vaev-engine/style/media.cpp Adds viewportSize() helper method to Media struct
src/vaev-engine/dom/window.cpp Adds refreshAsync() method and refactors viewport size usage
src/vaev-engine/dom/serialisation.cpp Implements HTML fragment serialization per WHATWG spec
src/vaev-engine/dom/names.cpp Adds documentation comment for namespace serialization logic
src/vaev-engine/dom/mod.cpp Exports new serialisation module
src/vaev-engine/dom/element.cpp Adds isVoidElement() method for HTML void element detection

Copy link
Member

@Louciole Louciole left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i let you fishish the TODO's but overall it looks good, I didn't see big loopholes, well done it's great !

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 17 comments.

27.94
};
Math::Insetsf margins = 1.0;
Vec<urange> pageRanges{};
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pageRanges field is defined but never used in the toNative() method or populated in service.cpp. Either implement support for page ranges or remove this field if it's not yet supported.

Suggested change
Vec<urange> pageRanges{};

Copilot uses AI. Check for mistakes.

[[clang::coro_wrapper]]
Async::Task<> refreshAsync() {
return loadLocationAsync(document()->url());
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null pointer dereference. The upgrade() call on a weak pointer in refreshAsync() (line 68) could return null if the document has been destroyed. Add error handling to check if the upgrade succeeds before calling url() on it.

Suggested change
return loadLocationAsync(document()->url());
auto doc = document();
if (!doc) {
co_return Error::invalidState("No document to refresh");
}
co_return co_await loadLocationAsync(doc->url());

Copilot uses AI. Check for mistakes.
Comment on lines +105 to +118
if (auto isValue = el->getAttribute(Html::IS_ATTR)) {
e(" is=\"");
escapeString(e, isValue.unwrap(), true);
e("\"");
}
// - For each attribute:
for (auto& [name, attr] : el->attributes.iterUnordered()) {
if (name == Html::IS_ATTR)
continue;
// Append space, attribute’s serialized name, "=", quote, escaped value, quote.
e(" {}=\"", name);
escapeString(e, attr->value, true);
e("\"");
}
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete attribute handling logic. On line 105, the code checks for the is attribute value but then inside the loop on line 112 it skips the is attribute if it's in the attributes map. However, if getAttribute returns a value on line 105, that same attribute should still be in the attributes map, leading to redundant attribute output or skipping. The logic should be clarified to avoid potential duplicate attribute serialization.

Copilot uses AI. Check for mistakes.
} else {
co_return Error::invalidInput("unsupported intent");
}

Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty line at the beginning of the scope should be removed according to coding guidelines.

Copilot generated this review using guidance from repository custom instructions.
// Let marginRight be the result of getting a property with default named "right" and with a default of 1 from margin.
auto marginRight = margin.getOr("right", 1);

// If any of marginTop, marginBottom, marginLeft, or marginRight is not a Number, or is less then 0, return error with error code invalid argument.
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in comment: "then" should be "than". The correct phrase is "less than".

Suggested change
// If any of marginTop, marginBottom, marginLeft, or marginRight is not a Number, or is less then 0, return error with error code invalid argument.
// If any of marginTop, marginBottom, marginLeft, or marginRight is not a Number, or is less than 0, return error with error code invalid argument.

Copilot uses AI. Check for mistakes.
Comment on lines +462 to +510
// TODO

// Let background be the result of getting a property with default named "background" and with default false from parameters.
auto background = parameters.getOr("background", false);

// If background is not a Boolean return error with error code invalid argument.
// TODO

// Let page be the result of getting a property with default named "page" and with a default of an empty Object from parameters.
auto page = parameters.getOr("page", Serde::Object{});

// Let pageWidth be the result of getting a property with default named "width" and with a default of 21.59 from page.
auto pageWidth = page.getOr("width", 21.59);

// Let pageHeight be the result of getting a property with default named "height" and with a default of 27.94 from page.
auto pageHeight = page.getOr("height", 27.94);

// If either of pageWidth or pageHeight is not a Number, or is less than (2.54 / 72), return error with error code invalid argument.
// TODO

// Let margin be the result of getting a property with default named "margin" and with a default of an empty Object from parameters.
auto margin = parameters.getOr("margin", Serde::Object{});

// Let marginTop be the result of getting a property with default named "top" and with a default of 1 from margin.
auto marginTop = margin.getOr("top", 1);

// Let marginBottom be the result of getting a property with default named "bottom" and with a default of 1 from margin.
auto marginBottom = margin.getOr("bottom", 1);

// Let marginLeft be the result of getting a property with default named "left" and with a default of 1 from margin.
auto marginLeft = margin.getOr("left", 1);

// Let marginRight be the result of getting a property with default named "right" and with a default of 1 from margin.
auto marginRight = margin.getOr("right", 1);

// If any of marginTop, marginBottom, marginLeft, or marginRight is not a Number, or is less then 0, return error with error code invalid argument.
// TODO

// Let shrinkToFit be the result of getting a property with default named "shrinkToFit" and with default true from parameters.
auto shrinkToFit = parameters.getOr("shrinkToFit", true);

// If shrinkToFit is not a Boolean return error with error code invalid argument.
// TODO

// Let pageRanges be the result of getting a property with default named "pageRanges" from parameters with default of an empty Array.
// TODO

// If pageRanges is not an Array return error with error code invalid argument.
// TODO
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple TODO comments mark unimplemented validation checks (lines 462, 468, 480, 498, 504, 510). According to coding guidelines, TODO should only be added if there's a plan to address it in a future PR. Consider either implementing the validation now or converting these to NOTE comments with an explanation of why validation is deferred.

Copilot generated this review using guidance from repository custom instructions.
auto window = try$(session->currentBrowsingContext());

// 3. Let title be the session's current top-level browsing context's active document's title.
return Ok(window->document().upgrade()->title());
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null pointer dereference. The upgrade() call on a weak pointer could return null if the document has been destroyed. Add error handling to check if the upgrade succeeds before calling title() on it.

Suggested change
return Ok(window->document().upgrade()->title());
auto doc = window->document().upgrade();
if (not doc)
return Error::invalidInput("document destroyed");
return Ok(doc->title());

Copilot uses AI. Check for mistakes.
if (eqCi(Str(#VALUE), name)) \
return Symbol::from(Str(#VALUE));
#include "defs/ns-svg-attr-names.inc"

Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty line added at beginning of scope. According to coding guidelines, empty lines at the beginning of scopes should be removed.

Copilot generated this review using guidance from repository custom instructions.
if (eqCi(Str(#VALUE), name)) \
return Symbol::from(Str(#VALUE));
#include "defs/ns-svg-tag-names.inc"

Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty line added at beginning of scope. According to coding guidelines, empty lines at the beginning of scopes should be removed.

Copilot generated this review using guidance from repository custom instructions.
} else if (ns == MathMl::NAMESPACE) {
displayNamespace = "mathml";
}

Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty line added at beginning of scope. According to coding guidelines, empty lines at the beginning of scopes should be removed.

Copilot generated this review using guidance from repository custom instructions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants