on master help sign in
Start basic svg support
commit036593f6f97d6e8c3279f2ca5d4f0cd6c0719401 authorRyan Levick <ryan.levick@gmail.com> dateFri 15 Mar 2019, 16:48 (8 years ago) parent9e2e4cb
4 files changed+81−4
js/change-list.js+25−2 src/builder.rs+8 src/change_list.rs+33 src/vdom.rs+15−2
js/change-list.js+25−2
@@ -175,6 +175,29 @@ const OP_TABLE = [
175175 const id = mem32[i++];
176176 changeList.dropString(id);
177177 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;
178201 }
179202];
180203
@@ -226,7 +249,7 @@ class ChangeList {
226249
227250 applyChangeRange(mem8, mem32, start, len) {
228251 const end = (start + len) / 4;
229− for (let i = start / 4; i < end; ) {
252+ for (let i = start / 4; i < end;) {
230253 const op = mem32[i++];
231254 i = OP_TABLE[op](this, mem8, mem32, i);
232255 }
@@ -247,7 +270,7 @@ class ChangeList {
247270 initEventsTrampoline(trampoline) {
248271 this.trampoline = trampoline;
249272 trampoline.mounted = true;
250− this.eventHandler = function(event) {
273+ this.eventHandler = function (event) {
251274 if (!trampoline.mounted) {
252275 throw new Error("invocation of listener after VDOM has been unmounted");
253276 }
src/builder.rs+8
@@ -856,6 +856,14 @@ builder_constructors! {
856856 /// element.
857857 slot;
858858 /// 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
859867 /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
860868 /// element.
861869 template;
src/change_list.rs+33
@@ -267,6 +267,24 @@ enum ChangeDiscriminant {
267267 /// dropString(id);
268268 /// ```
269269 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,
270288}
271289
272290// Allocation utilities to ensure that we only allocation sequences of `u32`s
@@ -361,6 +379,14 @@ impl ChangeList {
361379 self.op2(ChangeDiscriminant::SetAttribute, name_id, value_id);
362380 }
363381
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+
364390 pub(crate) fn emit_remove_attribute(&mut self, name: &str) {
365391 debug!("emit_remove_attribute({:?})", name);
366392 let name_id = self.ensure_string(name);
@@ -402,6 +428,13 @@ impl ChangeList {
402428 self.op1(ChangeDiscriminant::CreateElement, tag_name_id);
403429 }
404430
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+
405438 pub(crate) fn emit_new_event_listener(&mut self, listener: &Listener) {
406439 debug!("emit_new_event_listener({:?})", listener);
407440 let (a, b) = listener.get_callback_parts();
src/vdom.rs+15−2
@@ -463,7 +463,12 @@ impl VdomInnerExclusive {
463463 attributes,
464464 children,
465465 }) => {
466− self.change_list.emit_create_element(tag_name);
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 {
470+ self.change_list.emit_create_element(tag_name);
471+ }
467472 for l in listeners {
468473 unsafe {
469474 registry.add(l);
@@ -471,7 +476,15 @@ impl VdomInnerExclusive {
471476 self.change_list.emit_new_event_listener(l);
472477 }
473478 for attr in attributes {
474− self.change_list.emit_set_attribute(&attr.name, &attr.value);
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 {
486+ self.change_list.emit_set_attribute(&attr.name, &attr.value);
487+ }
475488 }
476489 for child in children {
477490 self.create(registry, child.clone());