Open Bug 1263317 Opened 8 years ago Updated 2 years ago

Expose Rust API to Debugger for Servo

Categories

(Core :: JavaScript Engine, enhancement)

enhancement

Tracking

()

People

(Reporter: fitzgen, Unassigned)

References

(Depends on 8 open bugs, Blocks 1 open bug)

Details

Attachments

(1 file, 1 obsolete file)

Servo does not have privileged JS code, and wants to keep it that way.

The Debugger API is currently exposed to privileged JS, but it is all implemented in C++. It is battle-hardened by the fuzzers, has incredible expressivity, and generally has a great track record.

To let servo build debugging tools without throwing away the Debugger API and starting afresh, we should consider exposing C-bindings to the Debugger API in js/public. Then Servo can wrap those bindings up in a nice Rust form.
Summary: Expose Debugger C-bindings in js/publich for Servo → Expose Debugger C-bindings in js/public for Servo
Rewriting the summary to reflect the real goal: a Rust API. Whether implementing the Rust API involves C or C++ bindings is an implementation detail.

------------

Shu: we talked briefly on IRC about restricting random JSAPI calls while inside debugger hooks for safety concerns. That sounds totally reasonable, but short of calling JS_DestroyRuntime, what specific kinds of JSAPI calls were you thinking would be problematic.

The biggest issues I can think of at the moment is accidentally running debuggee code, and I think we should be able to make DebuggeeWouldRun exceptions fatal since we don't have gecko's cruft in servo.
Flags: needinfo?(shu)
Summary: Expose Debugger C-bindings in js/public for Servo → Expose Rust API to Debugger for Servo
(In reply to Nick Fitzgerald [:fitzgen] [⏰PDT; UTC-7] from comment #1)
> what specific kinds of JSAPI calls
> were you thinking would be problematic.

That was supposed to end in a question mark...
(In reply to Nick Fitzgerald [:fitzgen] [⏰PDT; UTC-7] from comment #1)
> Rewriting the summary to reflect the real goal: a Rust API. Whether
> implementing the Rust API involves C or C++ bindings is an implementation
> detail.
> 
> ------------
> 
> Shu: we talked briefly on IRC about restricting random JSAPI calls while
> inside debugger hooks for safety concerns. That sounds totally reasonable,
> but short of calling JS_DestroyRuntime, what specific kinds of JSAPI calls
> were you thinking would be problematic.
> 
> The biggest issues I can think of at the moment is accidentally running
> debuggee code, and I think we should be able to make DebuggeeWouldRun
> exceptions fatal since we don't have gecko's cruft in servo.

My worry was that if debugger code is now Rust code that has JSAPI available to it, it needs to take care not to mutate the engine state from beneath it. While paused, the Debugger API (with its Rust bindings) should be the only way to interact with SM. That's a larger surface area than just preventing debuggee JS from executing.

I don't know enough about Servo to say how it would achieve this.
Flags: needinfo?(shu)
(In reply to Shu-yu Guo [:shu] from comment #3)
> My worry was that if debugger code is now Rust code that has JSAPI available
> to it, it needs to take care not to mutate the engine state from beneath it.
> While paused, the Debugger API (with its Rust bindings) should be the only
> way to interact with SM. That's a larger surface area than just preventing
> debuggee JS from executing.

Still though: What kind of bug specifically are you concerned about?

Right now, the Debugger object (with its JS bindings) deliberately reenters the engine as though by JS::Call(), which strikes me as exactly the same mutationiness level as most JSAPI entry points. It can allocate, it can GC, it can immediately try to re-enter the interpreter... the debugger already has to be prepared for all kinds of nonsense.
Note: we should use the rust port of quickcheck[0] to fuzz the rust API.

[0] https://github.com/BurntSushi/quickcheck
(In reply to Jason Orendorff [:jorendorff] from comment #4)
> (In reply to Shu-yu Guo [:shu] from comment #3)
> > My worry was that if debugger code is now Rust code that has JSAPI available
> > to it, it needs to take care not to mutate the engine state from beneath it.
> > While paused, the Debugger API (with its Rust bindings) should be the only
> > way to interact with SM. That's a larger surface area than just preventing
> > debuggee JS from executing.
> 
> Still though: What kind of bug specifically are you concerned about?
> 

I'm worried about allowing debugger code to, for example, set reserved slots, futz with TypedArray buffers, engine-internal operations that JSAPI allows you to do but regular JS doesn't.

> Right now, the Debugger object (with its JS bindings) deliberately reenters
> the engine as though by JS::Call(), which strikes me as exactly the same
> mutationiness level as most JSAPI entry points. It can allocate, it can GC,
> it can immediately try to re-enter the interpreter... the debugger already
> has to be prepared for all kinds of nonsense.

I'm not talking about mutation that happens through running JS. The Debugger obviously already handles all of that. But if rust debugger code can mutate through directly reaching into the guts of the engine, since JSAPI lets you do that, that worries me because Debugger doesn't expect that.

It could just be a matter of disciplined coding, and putting a hair shirt on JSAPI might be not worth it.
(In reply to Shu-yu Guo [:shu] from comment #6)
> I'm worried about allowing debugger code to, for example, set reserved
> slots, futz with TypedArray buffers, engine-internal operations that JSAPI
> allows you to do but regular JS doesn't.

Well, but regular JS can call JSNatives, and JSNatives have access to pretty much the whole API.

> It could just be a matter of disciplined coding, and putting a hair shirt on
> JSAPI might be not worth it.

More positively stated, whatever hairshirt you devise should probably have even broader applicability --- it could make all JSNatives safer.
(In reply to Shu-yu Guo [:shu] from comment #6)
> I'm not talking about mutation that happens through running JS. The Debugger
> obviously already handles all of that. But if rust debugger code can mutate
> through directly reaching into the guts of the engine, since JSAPI lets you
> do that, that worries me because Debugger doesn't expect that.
> 
> It could just be a matter of disciplined coding, and putting a hair shirt on
> JSAPI might be not worth it.

I think this risk is analogous to the risk that our present debugger server can use other sorts of cross-compartment wrappers (xray wrappers, say) to tweak debuggee state, without ever entering script. So it's a problem present in our Gecko implementation as well.

If the debugger server itself does these tweaks, I think that is probably going to be deliberate, and okay. What we need to worry about is the nested event loop letting other bits of platform code run that cause object state to change at a point when the mid-event-tick debuggee code wasn't expecting it to.

Although I don't understand the details, I'm told that Servo has an entirely different way to shut down processing of events in a particular page, and all the misery we have in Gecko just doesn't exist there; you can really pause the page. That suggests to me that random bits of platform helpfully modifying page state because it thinks it's running *between* the content's ticks, while the debugger has caused it to run *in the midst* of a content tick [breathe] will be less of a problem in Servo.
Assignee: nobody → ejpbruel
Idle question: does the Rust API belong in servo/mozjs or m-c?
servo/mozjs is intended to be a minimally-modified import of SpiderMonkey. servo/rust-mozjs would be a more feasible place for it, but it would be nice from our point of view if it were updated to accommodate changes in spidermonkey inside mozilla-central without us having to maintain it.
Blocks: 1263289
Whiteboard: [devtools-html]
(In reply to Nick Fitzgerald [:fitzgen] [⏰PDT; UTC-7] from comment #9)
> Idle question: does the Rust API belong in servo/mozjs or m-c?

I was wondering about this, too. Conceptually, it's a Rust API owned by SpiderMonkey. But this would be the first Rust code in SpiderMonkey, and I don't know what's entailed in making that work.

Can we just add Rust files to a moz.build file?

Do we use Cargo?

etc.
I definitely want this code to live in m-c. Calling larsberg for the build requirements.
Flags: needinfo?(larsberg)
You *should* just be able to do:

1) Add `ac_add_options --enable-rust` to your .mozconfig
2) Add the toplevel `lib.rs` file to `SOURCES` in your moz.build file. See e.g.:
http://mxr.mozilla.org/mozilla-central/source/media/libstagefright/moz.build#82
3) Note that adding tests via gtest was a little more compilcated:
http://mxr.mozilla.org/mozilla-central/source/media/libstagefright/gtest/

I'm shamelessly cribbing from examples written by :rillian here, which is the only currently shipping Rust code.

That said, I don't know if there are any SpiderMonkey-specific differences in the way the build system works. Drop by #build and we can chat with :froydnj and others who have been landing a bunch of improvements here lately to see if it does what you want.

I'll echo :Ms2ger that it would be awesome for this to live in m-c, as it'll ensure that we don't end up where we are with our SM Rust bindings - constantly broken and playing catch-up with API changes and usage of new bits of C++ that our bindings generator can't handle.
Flags: needinfo?(larsberg)
(In reply to Lars Bergstrom (:larsberg) from comment #13)
> I'll echo :Ms2ger that it would be awesome for this to live in m-c, as it'll
> ensure that we don't end up where we are with our SM Rust bindings -
> constantly broken and playing catch-up with API changes and usage of new
> bits of C++ that our bindings generator can't handle.

What's more, this would be a great somewhat contained version of something we could do for the bindings, too. Moving those into m-c is something we should do if at all possible.
Okay, great. Then we'll aim for Debugger API Rust bindings in M-C.
Depends on: 1267436
Depends on: 1267442
Depends on: 1267444
Depends on: 1267446
Depends on: 1267447
Depends on: 1267448
Depends on: 1267450
Severity: normal → enhancement
Attached patch First draft of the debugger API. (obsolete) (deleted) — Splinter Review
Our strategy here will be to write the API documentation first, so we know what our requirements are. Based on what we learn, we can then implement the C++ parts, and finally the actual bindings on top of that.

I've created a rough first draft of the API documentation which I think is enough as a basis to start our conversation. My main goal for this first draft was to define most of the relevant types and methods. Note that some methods that the JavaScript API defines still need to be done, and the documentation is still rudimentary. I've also added a number of FIXME comments in areas of the patch where I have questions.
Attachment #8745484 - Flags: feedback?(nfitzgerald)
Attachment #8745484 - Flags: feedback?(jimb)
Comment on attachment 8745484 [details] [diff] [review]
First draft of the debugger API.

Review of attachment 8745484 [details] [diff] [review]:
-----------------------------------------------------------------

Partial read-through.

::: src/lib.rs
@@ +3,5 @@
> +/// A type that described why an operation failed.
> +///
> +/// FIXME: The JavaScript API restricts itself to the built-in JavaScript error
> +/// exception types. For the Rust API, I've tried to come up with more
> +/// meaningful error types. Do you think this is reasonable?

Yes, we're definitely going to need our own vocabulary of errors.

Some of these errors get reported back across the debugging protocol. Those need to be fully distinguished. Other errors indicate a problem internal to the server, and probably aren't going to be terribly recoverable, so there's not much valuable in providing a separate variant for each specific case.

@@ +32,5 @@
> +///
> +/// FIXME: Servo also uses a Fallible type. Maybe we should reuse that, and add
> +/// the above error values to their Error type, instead of defining our own?
> +/// What do you think?
> +pub type Fallible<T> = Result<T, Error>;

I thought Rust practice was to have per-module Result types, like:

    pub type Result<T> = std::result::Result<T, Error>;

But if Servo does things differently, I'm not sure what that implies.

@@ +37,5 @@
> +
> +/// A value in the debuggee's compartment. A value is either a primitive value
> +/// or an object. A primitive value is either undefined, a boolean, a number,
> +/// a string, or null.
> +pub enum Value {

Ugh. Is there a reason we can't just use something like this?

    pub enum Value {
        Object(Object),
        Primitive(js::jsval::JSVal)
    }

@@ +76,5 @@
> +    pub get: Option<Value>,
> +
> +    /// If the value is an object, it must be callable, and will be used as a
> +    /// setter for the property. Otherwise, the value must be `Undefined`.
> +    pub set: Option<Value>

I think it would be better to have an enum:

    enum PropertyKind {
        Value(Value),
        Accessor { get: Option<Value>, set: Option<Value> }
    }

I take it the reason for the `Option<bool>` is that we can use this for reconfiguring properties, too? So `None` would mean "No change"?

@@ +85,5 @@
> +    /// The call returned a return value.
> +    Return(Value),
> +
> +    /// The call threw an exception value.
> +    Throw(Value)

Why no `Terminated` variant here?
Can we just make a C API which would later used by bindgen, as we already do for jsapi?

The reason I am saying that is that I think other embedders might want to use this API for the same reason, except that they might not want to depend on yet another language to do that.

Having this API written in rust is just adding overhead to SpiderMonkey, and does not bring any value, especially for an API which from what I understand is only forwarding variables.
A C or C++ API should be OK as long as you don't get too crazy with templates and enumerated types and whatever else.
If you do choose to do a C or C++ API, I still think it is useful to provide Rust bindings in js/public as well. For starters, they won't get out of date.
(In reply to Nicolas B. Pierron [:nbp] from comment #18)
> Can we just make a C API which would later used by bindgen, as we already do
> for jsapi?
> 
> The reason I am saying that is that I think other embedders might want to
> use this API for the same reason, except that they might not want to depend
> on yet another language to do that.
> 
> Having this API written in rust is just adding overhead to SpiderMonkey, and
> does not bring any value, especially for an API which from what I understand
> is only forwarding variables.

Here are my thoughts:

My understanding is that bindgen does a fairly straightforward AST transformation to convert a C API to a Rust API. The result is an API that, although written in Rust, is C-like in nature, and which doesn't take full advantage of the more powerful type system that Rust offers. This would be rather unfortunate: we'd like to take as much advantage of Rust's type system as we can, since this helps us to avoid a lot of common programming mistakes when using the debugger API.

However, I'd like to point out that in Servo, the debugger server will run in a different thread than the one it is debugging. The debugger API, on the other hand, is designed to be used within the same thread. This will require us to implement some form of rpc mechanism on top of the debugger API. This reduces the value of making the debugger API strongly typed, since these types will immediately be wrapped in rpc messages (the rpc mechanism is expected to be the only way in which we will use the debugger API in Servo).

Perhaps a viable compromise would be the following: in the debugger server's thread, we implement the debugger API as proposed above. However, instead of binding to the C/C++ objects directly, the objects in this API act as proxies for the corresponding objects in the debuggee's thread. The latter will be generated by bindgen from the corresponding C API.

This gives us the best of both worlds: it gives us the strongly typed API we want on the debugger server's thread (which is where we really care about it), while still allowing us to generate the bindings on the debuggee's thread from a C API, as nbp suggested.
I think Eddy makes a lot of solid points, but I also think it's valuable to put the type-safe API as close to SpiderMonkey as we can manage it. I don't think it's going to be any less work to get an intra-thread safe API, and then design the channel protocol to use that. And then the channel implementation itself can benefit from things like making the Debugger types !Send.
(In reply to Jack Moffitt [:jack] from comment #20)
> If you do choose to do a C or C++ API, I still think it is useful to provide
> Rust bindings in js/public as well. For starters, they won't get out of date.

Just to detail what this assumption implies:
 - You are assuming that any SpiderMonkey developer which modifies the API of the Debugger is capable of making changes to the Rust bindings.

I had to modify the Debugger a few times in the past, either by adding functions, or changing the prototype of others.  I barely have a clue on how to write an hello world in Rust.  So, you want me to maintain proper Rust bindings?

This choice seems good for Servo, as you will off-load the work to SpiderMonkey developers.  On the other hand, I won't bet on the quality of the bindings, if every SpiderMonkey developers are now responsible for maintaining these bindings.

Unless, making these bindings is just trivial that one does not even need to compile to get working code. It sounds to me that the responsibility would be put on the wrong persons.
Status: NEW → ASSIGNED
Iteration: --- → 49.1 - May 9
Flags: qe-verify-
Priority: -- → P1
(In reply to Nicolas B. Pierron [:nbp] from comment #23)
> I had to modify the Debugger a few times in the past, either by adding
> functions, or changing the prototype of others.  I barely have a clue on how
> to write an hello world in Rust.  So, you want me to maintain proper Rust
> bindings?

Yes - to the same extent that we're all expected to handle things we're not expert in.

This is one of the big questions in this bug: is it okay to introduce Rust code into the SpiderMonkey sources?

I don't know if it's still part of his plan, but at one point Jakob Olesen was planning to use Rust in the code generator he's working on. There, too, SpiderMonkey engineers could find themselves needing to update some Rust code from time to time. There could be other plans that involve introducing Rust into js/src. This bug is just one more case.

I think you're making the situation sound a little worse than it is. It is not true, for example, that every SpiderMonkey developer is automatically qualified to make good changes to Debugger, even though that's entirely C++. Sometimes one has to ask for help with things one doesn't have the background to handle oneself.
Comment on attachment 8745484 [details] [diff] [review]
First draft of the debugger API.

Review of attachment 8745484 [details] [diff] [review]:
-----------------------------------------------------------------

::: src/lib.rs
@@ +37,5 @@
> +
> +/// A value in the debuggee's compartment. A value is either a primitive value
> +/// or an object. A primitive value is either undefined, a boolean, a number,
> +/// a string, or null.
> +pub enum Value {

On second thought, this would reintroduce rooting questions that we don't want to expose.
(In reply to Jim Blandy :jimb from comment #24)
> Sometimes one has to ask for help with things one doesn't have the
> background to handle oneself.

To be clear, we're putting ourselves on the hook to provide this help and guidance. If SpiderMonkey can't get the support from us necessary to keep this a healthy part of the code base, then the Rust bindings should come out. It's no different from any other specialized feature.
Comment on attachment 8745484 [details] [diff] [review]
First draft of the debugger API.

Review of attachment 8745484 [details] [diff] [review]:
-----------------------------------------------------------------

Feedback+ for now, as per our meeting. Please re-request as necessary.
Attachment #8745484 - Flags: feedback?(jimb) → feedback+
Comment on attachment 8745484 [details] [diff] [review]
First draft of the debugger API.

Review of attachment 8745484 [details] [diff] [review]:
-----------------------------------------------------------------

Ditto.
Attachment #8745484 - Flags: feedback?(nfitzgerald) → feedback+
I think it would be way more reasonable to make a C or C++ API that we Servo people are responsible to bind, with our bindgen tools.

:jimb you just commented something about rooting, do you know the rooting story in Servo?
(In reply to nox from comment #29)
> :jimb you just commented something about rooting, do you know the rooting
> story in Servo?

Not really, but I'll have to understand it soon enough. If I'm missing something important, please let me know.

From my reading, it seemed like the js::jsval::JSVal is a direct export of the C++ JS::Value, which is unrooted. So my suggestion in comment 17 would have changed the enum Eddy proposed from something that handled rooting itself (probably using something like PersistentRooted) into something that required careful handling to be rooted, like JS::Value.

I haven't read further to understand how Servo itself takes care of ensuring values are rooted.

We want the boundary at which the code becomes "safe" in the Rust sense to be as close to SpiderMonkey as possible. It seems like that should include ensuring JS values are properly rooted.
We use `Rooted` and `Heap`.
I've revised the previous draft of the Rust debugger API based on Jim's and Nick's comments. In particular:

- The callback functions have been replaced with traits.
- These traits are passed as a refcounted box, instead of a just plain box.
- Added references to the existing debugger API documentation where appropriate.
- Added a section to each method describing its error return values.
- Added some notes on how certain methods are supposed to be used.
Attachment #8745484 - Attachment is obsolete: true
Comment on attachment 8749553 [details] [diff] [review]
Second draft of the debugger API.

Rc<Box<Trait>> is redundant; it should be possible to use Rc<Trait> instead. Why is Rc required, though?
(In reply to Josh Matthews [:jdm] from comment #33)
> Comment on attachment 8749553 [details] [diff] [review]
> Second draft of the debugger API.
> 
> Rc<Box<Trait>> is redundant; it should be possible to use Rc<Trait> instead.
> Why is Rc required, though?

The idea is that we want to be able to use a single object as both a PopHandler and a StepHandler. In that case, we have two owning references to a single object. Hence the use of Rc.
My main issues with this are:

1/ On what is that API based? We need FFI at some point right? Will SM start to maintain the bindings we generate ourselves in rust-mozjs? [1]

2/ How sure can we be that this is a viable API draft when Object is just an empty struct in it? To me it sounds like a crucial detail that might shoot us in the foot when we go further in this project.

[1] https://github.com/servo/rust-mozjs
Status: ASSIGNED → NEW
Iteration: 49.1 - May 9 → ---
Priority: P1 → P2
(In reply to Anthony Ramine [:nox] from comment #35)
> 1/ On what is that API based? We need FFI at some point right? Will SM start
> to maintain the bindings we generate ourselves in rust-mozjs? [1]

We do have a completely designed debugging API, documented in js/src/doc/Debugger, which we have five years of experience using. The Rust API is intended to be as thin a layer over that as possible while still being type safe. Surprises will come from interactions with Rust, not from the fundamental characteristics of the API. If you haven't already, you can take a look at that documentation to see the broad outlines the Rust debugging API will follow.

The idea is that SpiderMonkey will take on the maintenance of the Rust debugging API. Specifically, that would be Eddy, Nick, and myself, who are all SpiderMonkey peers. I think it would be best for SpiderMonkey to take on the rust-mozjs bindings as well, but that's out of scope for this bug.

> 2/ How sure can we be that this is a viable API draft when Object is just an
> empty struct in it? To me it sounds like a crucial detail that might shoot
> us in the foot when we go further in this project.

What you're observing in this bug is someone asking for feedback on a work in progress - not approval to land a patch. Some people prefer to have a complete design put together before letting anyone else see it, while others find it helpful to discuss things even while they're incomplete. I don't see that either is necessarily a problem. I don't think we're in a position to shoot ourselves in the foot yet, but be patient. :)

Clearly, the empty Object type is a stand-in for code that hasn't been written yet. So either you're expressing skepticism that we'll be able to fill that in with something that isn't broken (that's not very friendly - have we met?) or you're saying that having an Object type at all may be a mistake, which sounds surprising to me but could be an important insight.

If you've looked over the existing Debugger docs: Are there specific things you are hoping to see in this API that are missing? Are there specific points that seem wrong, or awkward, or limiting?
(In reply to Jim Blandy :jimb from comment #36)
> (In reply to Anthony Ramine [:nox] from comment #35)
> > 1/ On what is that API based? We need FFI at some point right? Will SM start
> > to maintain the bindings we generate ourselves in rust-mozjs? [1]

Okay, after the Vidyo meeting I feel like I have a much better understanding of Anthony's concerns here.

For technical reasons, it will be difficult to have the debugger Rust bindings in some crate located in js/src; but rust-mozjs providing JSAPI access in another crate from the outside, with both linking against the same SpiderMonkey. Things will be much simpler if the Rust Debugger API and the Rust JSAPI bindings are located in the same crate.

Whether that crate is located within SpiderMonkey or maintained separately is a separate question. Anthony explained that, at present, updating SpiderMonkey takes quite a lot of effort, for reasons detailed elsewhere, so it's necessary to minimize the number of "round trips": adding C++ APIs; import a fresh copy of SM into rust-mozjs; add Rust bindings for those APIs.

Ideally, the Rust bindings, both JSAPI and debugger, would live in js/src, and SpiderMonkey engineers would get CI failures if they break them. However, getting to that point will require investment on the order of an engineer quarter.

That's my understanding. Please correct as needed.
(In reply to Jim Blandy :jimb from comment #37)
> Ideally, the Rust bindings, both JSAPI and debugger, would live in js/src,
> and SpiderMonkey engineers would get CI failures if they break them.
> However, getting to that point will require investment on the order of an
> engineer quarter.

It took more than an engineer-quarter for the previous SpiderMonkey upgrade, and it is not far off from one for the current one that just landed. It would be much nicer to pay this cost once, pay much, much smaller incremental costs keeping the bindings up to date, than to keep spending engineer-quarters on giant updates.

Also, if we were to do this work moving rust-mozjs into js/src now, it would take much less time than if we wait a quarter or two, since we'll have gained a engineer-quarter's worth of update work in addition to the other tasks. Perhaps we should open a separate bug for that and block this one on it so we can start getting buy-in and moving that process forward.
Depends on: 1271641
I've added bug 1271641 as a dependency for this bug. That bug will be about implementing a C++ interface for the debugger API, from which we can then generate Rust bindings. This bug will be about implementing the higher level Rust interface proposed in this bug on top of the lower-level interface generated by the bindings.
(In reply to Jack Moffitt [:jack] from comment #38)
> It took more than an engineer-quarter for the previous SpiderMonkey upgrade,
> and it is not far off from one for the current one that just landed. It
> would be much nicer to pay this cost once, pay much, much smaller
> incremental costs keeping the bindings up to date, than to keep spending
> engineer-quarters on giant updates.

This is a continuous integration question, not about integrating it in SpiderMonkey.

If you add code in SpiderMonkey and never check for it, you will have the same problem.

Now, you can add the same test in rust-mozjs and not add impedance to SpiderMonkey.

So what would be the benefit of moving such code in SpiderMonkey repository (mozilla-central) knowing that we would not rely on it for Firefox?
Spoke with Eddy this morning and he confirmed this bug should be a meta giving all the dependencies.
Assignee: ejpbruel → nobody
Priority: P2 → --
Summary: Expose Rust API to Debugger for Servo → [meta-html] Expose Rust API to Debugger for Servo
Whiteboard: [devtools-html] → [meta-html] [devtools-html]
Whiteboard: [meta-html] [devtools-html] → [meta-html]
Summary: [meta-html] Expose Rust API to Debugger for Servo → Expose Rust API to Debugger for Servo
Whiteboard: [meta-html]
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: