|
| 1 | +Guide to Contributing |
| 2 | +===================== |
| 3 | + |
| 4 | +Thanks for contributing to scala-js-dom! |
| 5 | +We primarily accept PRs for: |
| 6 | +* Adding facades for APIs documented in the spec |
| 7 | +* Enhancing/fixing existing facades to match the spec |
| 8 | +* Adding non-facade Scala utilities to complement specific facades |
| 9 | +* Any other bug fixes etc. |
| 10 | + |
| 11 | +If you would like to make PR that doesn't fall under those categories, |
| 12 | +please raise an issue first for discussion so we can give you the go-ahead! |
| 13 | + |
| 14 | +We look forward to your PRs! |
| 15 | + |
| 16 | +Contents: |
| 17 | + |
| 18 | +* Packages |
| 19 | +* Files |
| 20 | +* Facades |
| 21 | +* Non-Facades |
| 22 | +* Binary Compatibility |
| 23 | +* Submitting a PR |
| 24 | + |
| 25 | + |
| 26 | +Packages |
| 27 | +======== |
| 28 | + |
| 29 | +In v1.x, there used to be sub-packages grouping some parts of the DOM API by major feature. |
| 30 | +In v2.x, we've decided to put everything in `org.scalajs.dom` and get rid of sub-packages. |
| 31 | + |
| 32 | +The reason for this change is that the real DOM API isn't namespaced in anyway, and the decision |
| 33 | +whether to group in a package or not, was subjective and inconsistent. |
| 34 | + |
| 35 | + |
| 36 | +Files |
| 37 | +===== |
| 38 | + |
| 39 | +* Use `package.scala` for a package object and nothing else. |
| 40 | + Also don't include traits/classes/objects. |
| 41 | + |
| 42 | +* Match the filename to the trait/class/object in it; don't add multiple top-level types. |
| 43 | + This is effectively Java-style. |
| 44 | + |
| 45 | + |
| 46 | +Facades |
| 47 | +======= |
| 48 | + |
| 49 | +We accept facades for any non-deprecated API documented in the spec, including experimental APIs or APIs not supported on all browsers. |
| 50 | +* MDN: https://developer.mozilla.org/en-US/docs/Web/API |
| 51 | +* WHATWG: https://spec.whatwg.org/ |
| 52 | + |
| 53 | +Please: |
| 54 | +* Use `def` for read-only properties unless there is a compelling reason it should be a `val` |
| 55 | + (i.e., the spec definitively states it is constant) |
| 56 | +* Use `Double` for integer-values that can fall outside the range of `Int` |
| 57 | +* Add scaladocs via copy-paste from MDN |
| 58 | + |
| 59 | + |
| 60 | +Non-Facades |
| 61 | +=========== |
| 62 | + |
| 63 | +* Implicit conversions should go in companion objects so that they are always in scope without the |
| 64 | + need for imports. There's no need to group by feature, the types already specify the feature. |
| 65 | + |
| 66 | +* Add Scala-only utilities that pertain to a specific facade, in the facades companion object |
| 67 | + Eg: helper constructors, legal facade values. |
| 68 | + |
| 69 | +* We currently don't see the need for Scala-only utilities that don't pertain to a specific facade, |
| 70 | + or shouldn't be universally available (subjective judgement here). |
| 71 | + If you believe you've got a compelling use case please raise an issue first to discuss. |
| 72 | + |
| 73 | +Binary Compatibility |
| 74 | +==================== |
| 75 | + |
| 76 | +Binary compatibility for Scala.js facades is different than standard Scala. |
| 77 | +The following are changes that are indeed incompatible in both formats: |
| 78 | + |
| 79 | +Don't: |
| 80 | + * Remove a trait / class / object |
| 81 | + * Change a class into a trait or vice versa |
| 82 | + |
| 83 | +Here is a non-exhaustive list of changes that would be binary-incompatible for Scala classes, but |
| 84 | +are compatible for JS facade types: |
| 85 | + |
| 86 | +You can: |
| 87 | + * Remove a member |
| 88 | + * Change the type or signature of a member |
| 89 | + * Add a field in a trait |
| 90 | + * Add an abstract member in a trait |
| 91 | + |
| 92 | +To help us enforce binary compatibility, we use API reports. |
| 93 | +They are auto-generated by running `prePR` in sbt and provide a concise summary of the entire API. |
| 94 | +Note: We might automate binary compatibility checking in the future (see #503) but for now, |
| 95 | +it's just a helpful tool for reviewing PRs. |
| 96 | + |
| 97 | +Here is an example of a binary _compatible_ change in #491 as it appears in the API report diff. |
| 98 | +Note that `[JC]` stands for **J**avascript **C**lass, indicating that `HTMLAudioElement` is a facade type and thus this is a compatible change. |
| 99 | +```diff |
| 100 | +-raw/HTMLAudioElement[JC] def play(): Unit |
| 101 | ++raw/HTMLAudioElement[JC] def play(): js.UndefOr[js.Promise[Unit]] |
| 102 | +``` |
| 103 | + |
| 104 | +Here is an example of a binary _incompatible_ change in #458 as it appears in the API report diff. |
| 105 | +Even though the `Fetch` object is a facade (a **J**avascript **O**bject), moving it out of the `experimental` package is not binary compatible. |
| 106 | +(In this particular case, the change was accepted along with many binary-breaking changes going into 2.0.0.) |
| 107 | +```diff |
| 108 | +-experimental/Fetch[JO] def fetch(info: RequestInfo, init: RequestInit = null): js.Promise[Response] |
| 109 | ++Fetch[JO] def fetch(info: RequestInfo, init: RequestInit = null): js.Promise[Response] |
| 110 | +``` |
| 111 | + |
| 112 | +Anything annotated `[SC]`, `[ST]`, or `[SO]` in an API report is an ordinary Scala class/trait/object, |
| 113 | +for which standard binary compatibility rules apply. |
| 114 | + |
| 115 | +If the above doesn't make sense to you, don't worry! |
| 116 | +The majority of useful changes to scala-js-dom are indeed binary compatible. |
| 117 | + |
| 118 | + |
| 119 | +Submitting a PR |
| 120 | +=============== |
| 121 | + |
| 122 | +Once you're done making your changes... |
| 123 | + |
| 124 | +1. Run `sbt prePR` |
| 125 | + |
| 126 | +2. Run `git diff api-reports` and ensure that you aren't breaking backwards-binary-compatibility |
| 127 | + (see above). |
| 128 | + |
| 129 | +3. Check in and commit the changes to `api-reports` |
| 130 | + |
| 131 | +4. Submit your PR |
| 132 | + |
| 133 | +5. Know that your contribution is appreciated, thank you! |
0 commit comments