Skip to content

Commit 9ad7523

Browse files
authored
Merge pull request #65 from mozilla-spidermonkey/esr17-migration-guide
Add ESR 10 to 17 migration guide
2 parents b80c70c + 9254297 commit 9ad7523

1 file changed

Lines changed: 252 additions & 0 deletions

File tree

docs/Migration Guide.md

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,3 +646,255 @@ This is a non-exhaustive list of minor API changes and renames.
646646
- `JS::FormatStackDump()` has removed its input buffer parameter.
647647
- `JS::GCForReason()``JS::NonIncrementalGC()`
648648
- `JS::GCPolicy<T>::initial()``JS::SafelyInitialized<T>`
649+
650+
## ESR 10 to 17 ##
651+
652+
At this time the JSAPI was still being documented in MDN.
653+
Viewing the pages on archive.org may give more details.
654+
[This](https://web.archive.org/web/20200424132803/https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_reference)
655+
is the last available snapshot, but older snapshots may be useful as
656+
well.
657+
658+
### Headers ###
659+
660+
The write barrier API (`JS_RegisterReference()`, `JS_ModifyReference()`,
661+
etc.) has moved from `jsapi.h` to `jsfriendapi.h`.
662+
663+
### C++ ###
664+
665+
At this point in SpiderMonkey's history, its headers could be compiled
666+
as either C or C++.
667+
There are a number of newer APIs behind an `#ifdef __cplusplus`, such as
668+
`JS::Value` and the Handle APIs.
669+
670+
**Recommendation:**
671+
If your codebase is in C, migrate it to C++.
672+
That will have to happen eventually anyway, as the C API gets removed in
673+
a future version.
674+
Migrating now will allow any new code that's being written to opt-in to
675+
future-proof APIs such as `JS::Value`.
676+
677+
### Types ###
678+
679+
Mozilla's custom integer types (`uint8`, `int32`, `JSUint64`, etc.) are
680+
deprecated, although still present in ESR 17.
681+
The standard types from `<stdint.h>` are preferred.
682+
683+
Other types have been removed in favour of plain C types:
684+
- `intN``int`
685+
- `jsdouble``double`
686+
- `jsint``int`
687+
- `jsrefcount``unsigned`
688+
- `jsuint``unsigned`
689+
- `jsuword``uintptr_t`
690+
- `jsword``intptr_t`
691+
- `uintN``unsigned`
692+
693+
**Recommendation:**
694+
Replace all occurrences of these types.
695+
696+
### Access from other threads ###
697+
698+
The `JS_THREADSAFE` build option is permanently turned on, meaning that
699+
JS APIs cannot be accessed from arbitrary threads.
700+
If your embedding relied on this, the code will probably need some
701+
refactoring.
702+
703+
APIs having to do with multi-threaded JS runtimes have all been removed:
704+
- `JS_ClearContextThread()`
705+
- `JS_GetContextThread()`
706+
- `JS_Lock()`
707+
- `JS_SetContextThread()`
708+
- `JS_Unlock()`
709+
710+
### JSClass ###
711+
712+
In this version there were several changes in the `JSClass` struct and
713+
its associated operations.
714+
715+
First of all, some of the members were reordered.
716+
Hopefully any affected code would fail to compile with the new ESR, but
717+
it's probably good to check all your `JSClass` definitions anyway.
718+
719+
The `JSClass.xdrObject` member was removed.
720+
It's likely that embedders were already not using JSXDR and were already
721+
setting this member to null.
722+
If you used this API, you may have to look for a custom solution.
723+
724+
Previously, a `JSClass` could provide either a `JSMarkOp` or `JSTraceOp`
725+
function pointer as the `JSClass.mark` member.
726+
The `JSCLASS_MARK_IS_TRACE` flag was used to indicate which one it was,
727+
and therefore how the function pointer would be called.
728+
The member has been renamed to `JSClass.trace`, and `JSMarkOp` has been
729+
removed, as well as `JSCLASS_MARK_IS_TRACE`.
730+
731+
If you had any `JSClass` with a non-null `mark` member that _didn't_ use
732+
`JSCLASS_MARK_IS_TRACE`, you must rewrite the mark operation as a trace
733+
operation.
734+
In most cases this should consist of a pretty straightforward
735+
replacement of `JS_MarkGCThing()` with `JS_CALL_TRACER()` and updating
736+
the function signature.
737+
An example is
738+
[here](https://bugzilla.mozilla.org/attachment.cgi?id=516449&action=diff#a/js/src/shell/js.cpp_sec2).
739+
740+
Several other `JSClass` operations, such as `JSPropertyOp`, changed
741+
their signatures to take Handles instead of pointers.
742+
Handles are part of the C++ API, although there are some alternate
743+
[typedefs](https://searchfox.org/mozilla-esr17/source/js/src/jsapi.h#1650)
744+
for use in the C API.
745+
746+
You will need to update the signatures of the class operations to match
747+
the new definitions.
748+
The definition of `JSPropertyOp`, for example, changed as follows:
749+
750+
```c++
751+
// old
752+
typedef JSBool (*JSPropertyOp)(JSContext*, JSObject*, jsid, jsval*);
753+
// new
754+
typedef JSBool (*JSPropertyOp)(JSContext*, JSHandleObject, JSHandleId, JSMutableHandleValue);
755+
```
756+
757+
If you are using C++ (recommended), you may need to use the Handle's
758+
`get()` or `address()` methods if you need access to the underlying
759+
GC-rooted thing, and `set()` if you need to set the value in a mutable
760+
Handle.
761+
For embeddings that still use C, use the `._` member of the ersatz
762+
Handle typedef or just cast the Handle to a pointer to the underlying
763+
GC thing, which should share the same memory layout (e.g. `(JSObject**)`
764+
for `JSHandleObject`).
765+
766+
`JSFinalizeOp`'s `JSContext*` parameter was replaced with a `JSFreeOp*`
767+
parameter.
768+
This is normally not used by embeddings.
769+
770+
There are some other minor removals listed below in the "Various API
771+
changes" section.
772+
773+
**Recommendations:**
774+
- Double-check your `JSClass` definitions to make sure the members
775+
match the new order.
776+
- Remove any usage of `JSCLASS_MARK_IS_TRACE`.
777+
- If you have any `JSMarkOp` functions, port them to match the signature
778+
of `JSTraceOp`.
779+
- Update signatures of other class operations where needed, to use the
780+
Handle API.
781+
782+
### E4X ###
783+
784+
E4X support (inline XML in JS) is being phased out at this point.
785+
If your code uses E4X, you'll need to pass `JSOPTION_ALLOW_XML` and
786+
possibly `JSOPTION_MOAR_XML` to `JS_SetOptions()` in order for it to
787+
keep working.
788+
789+
However, E4X is a dead end in terms of standardization, and is removed
790+
altogether in the very next version of SpiderMonkey, so the
791+
recommendation is to migrate your code not to use it.
792+
There isn't a one-size-fits-all replacement; some options are
793+
transpilation, parsing the XML from a string, and writing new APIs that
794+
take plain objects.
795+
796+
### GC callbacks ###
797+
798+
The old GC callback API has been split up.
799+
GC callbacks are now called only when GC begins and ends, and is passed
800+
a `JSGCStatus` value of `JSGC_BEGIN` or `JSGC_END`.
801+
For the finalize phase, there is a separate callback API that is set
802+
with `JS_SetFinalizeCallback()`, and is passed a `JSFinalizeStatus`
803+
value of `JSFINALIZE_START` or `JSFINALIZE_END`.
804+
This replaces the old `JSGCStatus` values of `JSGC_MARK_END` and
805+
`JSGC_FINALIZE_END`.
806+
807+
`JS_SetGCCallback()` and `JS_SetGCCallbackRT()` have been combined into
808+
a single `JS_SetGCCallback()` API that takes `JSRuntime*` instead of
809+
`JSContext*`.
810+
811+
**Recommendation:**
812+
If your GC callback performed any actions on `JSGC_MARK_END` or
813+
`JSGC_FINALIZE_END`, you'll need to split that code out into a separate
814+
finalize callback.
815+
You may need to fix up some API calls that take `JSRuntime*` instead of
816+
`JSContext*` (see also "Various API changes" below).
817+
Use `JS_GetRuntime()` or `JS_GetObjectRuntime()` if you don't have a
818+
pointer to the runtime already.
819+
820+
### Various API changes ###
821+
822+
This is a non-exhaustive list of minor API changes and renames.
823+
824+
- `JS_BufferIsCompilableUnit()` gets a boolean "bytes are UTF-8"
825+
argument in position 2.
826+
Previously, the bytes were not treated as UTF-8.
827+
- `JS_CompileFile()` → `JS_CompileUTF8File()`
828+
- `JS_CompileFileHandle()` → `JS_CompileUTF8FileHandle()`
829+
- `JS_CompileFileHandleForPrinicpals()` →
830+
`JS_CompileUTF8FileHandleForPrincipals()`
831+
- `JS_CompileFileHandleForPrinicpalsVersion()` →
832+
`JS_CompileUTF8FileHandleForPrincipalsVersion()`
833+
- Several APIs now take a `JSRuntime*` instead of a `JSContext*`:
834+
- `JS_CompartmentGC()`
835+
- `JS_DumpHeap()`
836+
- `JS_GC()`
837+
- `JS_IsInRequest()`
838+
- `JS_SetNativeStackQuota()`
839+
- `JS_TracerInit()`
840+
- Several APIs no longer take a `JSContext*` as the first argument:
841+
- `JS_GetClass()`
842+
- `JS_GetCompartmentPrivate()`
843+
- `JS_GetParent()`
844+
- `JS_GetPrivate()`
845+
- `JS_GetPrototype()`
846+
- `JS_GetReservedSlot()`
847+
- `JS_IsAboutToBeFinalized()`
848+
- `JS_SetCompartmentPrivate()`
849+
- `JS_SetPrivate()`
850+
- `JS_SetReservedSlot()`
851+
- `JSIdArray` is now opaque.
852+
Instead of accessing the `.length` and `.vector` members, use
853+
`JS_IdArrayLength()` and `JS_IdArrayGet()`.
854+
- `JS_NewCompartmentAndGlobalObject()` → `JS_NewGlobalObject()`
855+
- `JS_NewObjectForConstructor()` now takes an additional `JSClass*`
856+
argument.
857+
- `JS_Remove___Root()` functions no longer have a return value.
858+
- `JSTraceCallback` is passed a `void**` pointer to the traced pointer,
859+
instead of the `void*` pointer itself.
860+
861+
The following APIs have been removed.
862+
863+
- `JSCLASS_CONCURRENT_FINALIZER`: objects with finalize hooks are never
864+
finalized on a background thread anymore.
865+
- `JSCLASS_CONSTRUCT_PROTOTYPE`: this flag caused a class's constructor
866+
to be called once on its prototype object.
867+
If you need to do any initialization on the prototype object, do it
868+
after initializing the class instead.
869+
- `JS_ConstructObject()` and `JS_ConstructObjectWithArguments()`: use
870+
`JS_New()` instead, and pass a pointer to the constructor object.
871+
The old APIs would malfunction if the constructor was no longer
872+
reachable from the global object.
873+
- `JS_DestroyContextMaybeGC()`: use either `JS_DestroyContext()` or
874+
`JS_DestroyContextNoGC()`.
875+
- `JSFinalizeStub`: use null instead.
876+
(Despite the comment in `jsapi.h` that says `JSClass.finalize` must
877+
not be null!)
878+
- `JS_FlushCaches()`: no replacement.
879+
- `JS_GET_CLASS` macro: use `JS_GetClass()` instead.
880+
- `JS_IsConstructing_PossiblyWithGivenThisObject()`: once no longer
881+
using `JS_ConstructObject()` and `JSCLASS_CONSTRUCT_PROTOTYPE`, this
882+
can be replaced with `JS_IsConstructing()`.
883+
- `JS_IsScriptFrame()`: can be replaced by `JS_GetFrameScript()` which
884+
returns null if the frame is not a script frame.
885+
- `JS::MarkRuntime()`: this was an internal function and was unlikely to
886+
be used by embeddings.
887+
- `JS_NewNumberValue()`: use `JS_NumberValue()` instead, but note that
888+
the semantics are slightly different: it canonicalizes NaN, and it
889+
cannot fail.
890+
- `JSOPTION_JIT`, `JSOPTION_PROFILING`: no replacement.
891+
- `JSOPTION_SOFTEN`: Use `JS_SetJitHardening()` instead.
892+
- The `JSPD_ARGUMENT` flag for property descriptors: in ESR 17 you can
893+
assume that it's always set.
894+
- `JS_SetThreadStackLimit()`: use `JS_SetNativeStackQuota()` instead.
895+
- `JSVAL_IS_OBJECT()`: a drop-in replacement is
896+
`JSVAL_IS_NULL(v) || !JSVAL_IS_PRIMITIVE(v)`, but the long-term
897+
recommendation is to migrate to the C++ `JS::Value` API (see above.)
898+
Note that `JSVAL_IS_OBJECT()` corresponds to
899+
`JS::Value::isObjectOrNull()`, not `JS::Value::isObject()`.
900+
- `JS::Value::setObjectOrUndefined()`: open-code this if you need it.

0 commit comments

Comments
 (0)