on master help sign in
Start basic svg support
036593fRyan Levick
js/change-list.js+25−2
@@ -175,6 +175,29 @@ const OP_TABLE = [
175 const id = mem32[i++];
175 const id = mem32[i++];
176 changeList.dropString(id);
176 changeList.dropString(id);
177 return i;
177 return i;
178+ },
179+
180+ // 16
181+ function createElementNS(changeList, mem8, mem32, i) {
182+ const tagNameId = mem32[i++];
183+ const tagName = changeList.getString(tagNameId);
184+ const nsId = mem32[i++];
185+ const ns = changeList.getString(nsId);
186+ changeList.stack.push(document.createElementNS(ns, tagName));
187+ return i;
188+ },
189+
190+ // 17
191+ function setAttributeNS(changeList, mem8, mem32, i) {
192+ const nameId = mem32[i++];
193+ const valueId = mem32[i++];
194+ const nsId = mem32[i++];
195+ const name = changeList.getString(nameId);
196+ const value = changeList.getString(valueId);
197+ const ns = changeList.getString(nsId);
198+ const node = top(changeList.stack);
199+ node.setAttributeNS(ns, name, value);
200+ return i;
178 }
201 }
179];
202];
180
203
@@ -226,7 +249,7 @@ class ChangeList {
226
249
227 applyChangeRange(mem8, mem32, start, len) {
250 applyChangeRange(mem8, mem32, start, len) {
228 const end = (start + len) / 4;
251 const end = (start + len) / 4;
229− for (let i = start / 4; i < end; ) {
252+ for (let i = start / 4; i < end;) {
230 const op = mem32[i++];
253 const op = mem32[i++];
231 i = OP_TABLE[op](this, mem8, mem32, i);
254 i = OP_TABLE[op](this, mem8, mem32, i);
232 }
255 }
@@ -247,7 +270,7 @@ class ChangeList {
247 initEventsTrampoline(trampoline) {
270 initEventsTrampoline(trampoline) {
248 this.trampoline = trampoline;
271 this.trampoline = trampoline;
249 trampoline.mounted = true;
272 trampoline.mounted = true;
250− this.eventHandler = function(event) {
273+ this.eventHandler = function (event) {
251 if (!trampoline.mounted) {
274 if (!trampoline.mounted) {
252 throw new Error("invocation of listener after VDOM has been unmounted");
275 throw new Error("invocation of listener after VDOM has been unmounted");
253 }
276 }
src/builder.rs+8
@@ -856,6 +856,14 @@ builder_constructors! {
856 /// element.
856 /// element.
857 slot;
857 slot;
858 /// Build a
858 /// Build a
859+ /// [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
860+ /// element.
861+ svg;
862+ /// Build a
863+ /// [`<path>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path)
864+ /// element.
865+ path;
866+ /// Build a
859 /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
867 /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
860 /// element.
868 /// element.
861 template;
869 template;
src/change_list.rs+33
@@ -267,6 +267,24 @@ enum ChangeDiscriminant {
267 /// dropString(id);
267 /// dropString(id);
268 /// ```
268 /// ```
269 DropString = 15,
269 DropString = 15,
270+
271+ /// Immediates: `(pointer, length)`
272+ ///
273+ /// Stack: `[...] -> [... Node]`
274+ ///
275+ /// ```text
276+ /// stack.push(createElement(String(pointer, length))
277+ /// ```
278+ CreateElementNS = 16,
279+
280+ /// Immediates: `(pointer, length)`
281+ ///
282+ /// Stack: `[...] -> [... Node]`
283+ ///
284+ /// ```text
285+ /// stack.push(createElement(String(pointer, length))
286+ /// ```
287+ SetAttributeNS = 17,
270}
288}
271
289
272// Allocation utilities to ensure that we only allocation sequences of `u32`s
290// Allocation utilities to ensure that we only allocation sequences of `u32`s
@@ -361,6 +379,14 @@ impl ChangeList {
361 self.op2(ChangeDiscriminant::SetAttribute, name_id, value_id);
379 self.op2(ChangeDiscriminant::SetAttribute, name_id, value_id);
362 }
380 }
363
381
382+ pub(crate) fn emit_set_attribute_ns(&mut self, name: &str, value: &str, ns: &str) {
383+ debug!("emit_set_attribute_ns({:?}, {:?})", name, value, ns);
384+ let ns_id = self.ensure_string(ns);
385+ let name_id = self.ensure_string(name);
386+ let value_id = self.ensure_string(value);
387+ self.op3(ChangeDiscriminant::SetAttributeNS, name_id, value_id, ns_id);
388+ }
389+
364 pub(crate) fn emit_remove_attribute(&mut self, name: &str) {
390 pub(crate) fn emit_remove_attribute(&mut self, name: &str) {
365 debug!("emit_remove_attribute({:?})", name);
391 debug!("emit_remove_attribute({:?})", name);
366 let name_id = self.ensure_string(name);
392 let name_id = self.ensure_string(name);
@@ -402,6 +428,13 @@ impl ChangeList {
402 self.op1(ChangeDiscriminant::CreateElement, tag_name_id);
428 self.op1(ChangeDiscriminant::CreateElement, tag_name_id);
403 }
429 }
404
430
431+ pub(crate) fn emit_create_element_ns(&mut self, tag_name: &str, ns: &str) {
432+ debug!("emit_create_element_ns({:?}, {:?})", tag_name, ns);
433+ let tag_name_id = self.ensure_string(tag_name);
434+ let ns_id = self.ensure_string(ns);
435+ self.op2(ChangeDiscriminant::CreateElementNS, tag_name_id, ns_id);
436+ }
437+
405 pub(crate) fn emit_new_event_listener(&mut self, listener: &Listener) {
438 pub(crate) fn emit_new_event_listener(&mut self, listener: &Listener) {
406 debug!("emit_new_event_listener({:?})", listener);
439 debug!("emit_new_event_listener({:?})", listener);
407 let (a, b) = listener.get_callback_parts();
440 let (a, b) = listener.get_callback_parts();
src/vdom.rs+15−2
@@ -463,7 +463,12 @@ impl VdomInnerExclusive {
463 attributes,
463 attributes,
464 children,
464 children,
465 }) => {
465 }) => {
466+ if ["svg", "path"].contains(&tag_name) {
467+ self.change_list
468+ .emit_create_element_ns(tag_name, "http://www.w3.org/2000/svg");
469+ } else {
466− self.change_list.emit_create_element(tag_name);
470+ self.change_list.emit_create_element(tag_name);
471+ }
467 for l in listeners {
472 for l in listeners {
468 unsafe {
473 unsafe {
469 registry.add(l);
474 registry.add(l);
@@ -471,7 +476,15 @@ impl VdomInnerExclusive {
471 self.change_list.emit_new_event_listener(l);
476 self.change_list.emit_new_event_listener(l);
472 }
477 }
473 for attr in attributes {
478 for attr in attributes {
479+ if ["svg", "path"].contains(&tag_name) {
480+ self.change_list.emit_set_attribute_ns(
481+ &attr.name,
482+ &attr.value,
483+ "http://www.w3.org/2000/svg",
484+ );
485+ } else {
474− self.change_list.emit_set_attribute(&attr.name, &attr.value);
486+ self.change_list.emit_set_attribute(&attr.name, &attr.value);
487+ }
475 }
488 }
476 for child in children {
489 for child in children {
477 self.create(registry, child.clone());
490 self.create(registry, child.clone());