|
| 1 | +# Contributing |
| 2 | + |
| 3 | +First be forewarned: Contributions are wanted and dearly desired, but @aapoalas |
| 4 | +is a pain to deal with. He'll nitpick your PR to the bone if he happens to be in |
| 5 | +the mood to do so. He's not doing it to be evil or anything, he's just an idiot. |
| 6 | +Please forgive him, if you can. |
| 7 | + |
| 8 | +The second warning is: There is currently no license in place for Nova. The |
| 9 | +license will be some sort of open source license, but whether it'll be some |
| 10 | +copyleft license or just MIT is still undecided. At the end of the day, |
| 11 | +@aapoalas (again with that guy) has some aspirations of making this project be |
| 12 | +bigger than just a hobby-engine. If that day comes, it'd be nice to get more |
| 13 | +than a warm handshake out of it. Hence the ongoing lack of license. |
| 14 | + |
| 15 | +## List of active development ideas |
| 16 | + |
| 17 | +Here are some good ideas on what you can contribute to. |
| 18 | + |
| 19 | +### Technical points |
| 20 | + |
| 21 | +The heap will need to be concurrently marked at some point. Additionally, we'll |
| 22 | +want to split some heap data structures into two or more parts; only the |
| 23 | +commonly used parts should be loaded into L1 cache during common engine |
| 24 | +operations. |
| 25 | + |
| 26 | +For this purpose we'll need our own `Vec`, `Vec2`, `Vec3` and possibly other |
| 27 | +vector types. The first order of business is to get the length and capacity to |
| 28 | +be stored as a `u32`. The second will be enabling the splitting of heap data |
| 29 | +structures; this sbould work in a way similar to `ParallelVec` so that the size |
| 30 | +of `Vec2` and `Vec3` stays equal to `Vec`. |
| 31 | + |
| 32 | +Then finally, at some point we'll also want to make the whole heap thread-safe. |
| 33 | +Heap vectors (`Vec`, `Vec2`, ...) will become RCU-based, so when they expand (on |
| 34 | +push) they will return a `None` or `Some(droppable_vec)` which can either be |
| 35 | +dropped immediately (if concurrent heap marking is not currently ongoing) or |
| 36 | +pushed into a "graveyard" `UnsafeCell<Vec<(*mut (), fn(*mut ()))>>` that gets |
| 37 | +dropped at the end of a mark-and-sweep iteration. |
| 38 | + |
| 39 | +These and other technical work items can be found from the GitHub issues with |
| 40 | +the |
| 41 | +[`technical` label](https://github.com/trynova/nova/issues?q=is%3Aopen+is%3Aissue+label%3Atechnical+). |
| 42 | + |
| 43 | +### Internal methods of exotic objects |
| 44 | + |
| 45 | +ECMAScript spec has a ton of exotic objects. Most of these just have some extra |
| 46 | +internal slots while others change how they interact with user actions like |
| 47 | +get-by-identifier or get-by-value etc. |
| 48 | + |
| 49 | +You can easily find exotic objects' internal methods by searching for |
| 50 | +`"fn internal_get_prototype_of("` in the code base. Many of these matches will |
| 51 | +be in files that contain a lot of `todo!()` points. As an example, |
| 52 | +[proxy.rs](./nova_vm/src/ecmascript/builtins/proxy.rs) is currently entirely |
| 53 | +unimplemented. The internal methods of Proxies can be found |
| 54 | +[here](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots): |
| 55 | +These abstract internal methods would need to be translated into Nova Rust code |
| 56 | +in the `proxy.rs` file. |
| 57 | + |
| 58 | +[This PR](https://github.com/trynova/nova/pull/174) can perhaps also serve as a |
| 59 | +good guide into how internal methods are implemented: Especially check the first |
| 60 | +and third commits. One important thing for internal method implementations is |
| 61 | +that whenever a special implementation exists in the spec, our internal method |
| 62 | +should link to it. Another thing is that if you cannot figure out what you |
| 63 | +should be calling in the method or the method you should be calling doesn't |
| 64 | +exist yet and you think implementing it would be too much work, it is perfectly |
| 65 | +fine to simply add a `todo!()` call to punt on the issue. |
| 66 | + |
| 67 | +### Builtin functions |
| 68 | + |
| 69 | +Even more than internal methods, the ECMAScript spec defines builtin functions. |
| 70 | +The Nova engine already includes bindings for nearly all of them (only some |
| 71 | +Annex B functions should be missing) but the bindings are mostly just `todo!()` |
| 72 | +calls. |
| 73 | + |
| 74 | +Implementing missing builtin functions, or at least the easy and commonly used |
| 75 | +parts of them, is a massive and important effort. You can find a mostly |
| 76 | +exhaustive list of these (by constructor or prototype, or combined) |
| 77 | +[in the GitHub issue tracker](https://github.com/trynova/nova/issues?q=is%3Aopen+is%3Aissue+label%3A%22builtin+function%22). |
| 78 | + |
| 79 | +### Other things |
| 80 | + |
| 81 | +This list serves as a "this is where you were" for returning developers as well |
| 82 | +as a potential easy jumping-into point for newcompers. |
| 83 | + |
| 84 | +- Write implementations of more abstract operations |
| 85 | + - See `nova_vm/src/ecmascript/abstract_operations` |
| 86 | + - Specifically eg. `operations_on_objects.rs` is missing multiple operations, |
| 87 | + even stubs. |
| 88 | + |
| 89 | +Some more long-term prospects and/or wild ideas: |
| 90 | + |
| 91 | +- Reintroduce lifetimes to Heap if possible |
| 92 | + - `Value<'gen>` lifetime that is "controlled" by a Heap generation number: |
| 93 | + Heap Values are valid while we can guarantee that the Heap generation number |
| 94 | + isn't mutably borrowed. This is basically completely equal to a scope based |
| 95 | + `Local<'a, Value>` lifetime but the intended benefit is that the |
| 96 | + `Value<'gen>` lifetimes can also be used during Heap compaction: When Heap |
| 97 | + GC and compaction occurs it can be written as a transformation from |
| 98 | + `Heap<'old>` to `Heap<'new>` and the borrow checker would then help to make |
| 99 | + sure that any and all `T<'new>` structs within the heap are properly |
| 100 | + transformed to `T<'new>`. |
| 101 | +- Add a `Reference` variant to `Value` (or create a `ValueOrReference` enum that |
| 102 | + is the true root enum) |
| 103 | + - ReferenceRecords would (maybe?) move to Heap directly. This might make some |
| 104 | + syntax-directed operations simpler to implement. |
| 105 | +- Add `DISCRIMINANT + 0x80` variants that work as thrown values of type |
| 106 | + `DISCRIMINANT` |
| 107 | + - As a result, eg. a thrown String would be just a String with the top bit set |
| 108 | + true. This would stop Result usage which is a darn shame (can be fixed with |
| 109 | + Nightly features). But it would mean that returning a (sort of) |
| 110 | + `Result<Value>` would fit in a register. |
| 111 | +- Consider a register based VM instead of going stack based |
0 commit comments