GciForJavaScript
JavaScript FFI wrapper for GemStone C Interface (GCI)
GemStone is an object database and Smalltalk application runtime environment. You interact with the database through a dynamically linked C library available for Linux, macOS, and Windows. To use a C library from JavaScript we use ffi-napi, a foreign function library wrapper that allows us to define C types, structures, and function entry points, then load and call a C library.
GemBuilder for C documentation (HTML or PDF) describes the API for the single-threaded GCI library. We are using a new thread-safe library that has fewer functions (but more features). It is not separately documented, but has a header file, gcits.hf
, that is the definitive specification (a recent copy is included with this checkout).
The needed C libraries are not included as part of this checkout since there is a different set of libraries for each platform (*.so for Linux, *.dylib for macOS, and *.dll for Windows), and for each GemStone version. You should download a recent version and the appropriate product for your platform. Then move the appropriate files into the directory of your choice. As of 3.5.2, the required files were the following:
- libgcits-3.5.2-64.*
- libkrb5-3.5.2-64.*
- libssl-3.5.2-64.*
The default location is ./lib/
, but you can place them anywhere. The file ./src/GciDefault.js
contains a default config file that will be copied to ./GciLogin.js
. You can edit the library
attribute in that file to point to the actual libgcits
library (either a relative or an absolute path).
Files
We use index.js to import GciSession which has the primary public API. This is strictly a proof-of-concept, and is used by VSCode-GemStone.
Tests
With the Jest extension, create a debug configuration and run to see the tests.
Contributing Code
To add new function wrappers follow these steps:
- Identify a new function from
gcits.hf
(pick from the list below); - Add it to GciLibrary with the appropriate name, arguments, and return type;
- Add a wrapper function to GciSession to provide a JavaScript-like API;
- Add a test to show that it works; and, finally,
- Submit a pull request!
For inspiration, see GciForPython.
Function List
Desired Functions
The following provides a list of all the functions defined in gcits.hf
grouped to roughly parallel the tables in the GemBuilder for C manual. Checked items have been completed.
Table 7.1 Functions for Controlling Sessions and Transactions
✓ BoolType GciTsAbort(GciSession sess, GciErrSType *err);✓ BoolType GciTsBegin(GciSession sess, GciErrSType *err);✓ BoolType GciTsCommit(GciSession sess, GciErrSType *err);✓ char* GciTsEncrypt(const char* password, char *outBuf, size_t outBuffSize);✓ int GciTsSessionIsRemote(GciSession sess);✓ GciSession GciTsLogin(...);✓ BoolType GciTsLogout(GciSession sess, GciErrSType *err);
Table 7.2 Functions for Handling Errors and Interrupts and for Debugging
✓ BoolType GciTsBreak(GciSession sess, BoolType hard, GciErrSType *err);✓ int GciTsCallInProgress(GciSession sess, GciErrSType *err);✓ BoolType GciTsClearStack(GciSession sess, OopType gsProcess, GciErrSType *err);✓ OopType GciTsContinueWith(GciSession sess, ...);✓ int GciTsGemTrace(GciSession sess, int enable, GciErrSType *err);
Table 7.3 Functions for Managing Object Bitmaps
✓ BoolType GciTsReleaseObjs(GciSession sess, OopType *buf, int count, GciErrSType *err);✓ BoolType GciTsReleaseAllObjs(GciSession sess, GciErrSType *err);✓ BoolType GciTsSaveObjs(GciSession sess, OopType *buf, int count, GciErrSType *err);
Table 7.4 Functions for Compiling and Executing Smalltalk Code in the Database
✓ OopType GciTsCompileMethod(GciSession sess, ...);✓ BoolType GciTsProtectMethods(GciSession sess, BoolType mode, GciErrSType *err);✓ OopType GciTsExecute(GciSession sess, ...);✓ OopType GciTsExecute_(GciSession sess, ...);✓ ssize_t GciTsExecuteFetchBytes(GciSession sess, ...);✓ OopType GciTsPerform(GciSession sess, ...);✓ ssize_t GciTsPerformFetchBytes(GciSession sess, ...);
Table 7.5 Functions for Accessing Symbol Dictionaries
✓ OopType GciTsResolveSymbol(GciSession sess, ...);✓ OopType GciTsResolveSymbolObj(GciSession sess, ...);
Table 7.6 Functions for creating and Initializing Objects
✓ int GciTsGetFreeOops(GciSession sess, OopType *buf, int numOopsRequested, GciErrSType *err);✓ OopType GciTsNewObj(GciSession sess, OopType aClass, GciErrSType *err);✓ OopType GciTsNewByteArray(GciSession sess, ...);✓ OopType GciTsNewString_(GciSession sess, ...);✓ OopType GciTsNewSymbol(GciSession sess, ...);✓ OopType GciTsNewUnicodeString_(GciSession sess, ...);✓ OopType GciTsNewUtf8String_(GciSession sess, ...);✓ int64 GciTsFetchUnicode(GciSession sess, ...);
Table 7.7 Functions for Converting Objects and Values
✓ BoolType GciTsOopIsSpecial(OopType oop);✓ OopType GciTsFetchSpecialClass(OopType oop);✓ int GciTsOopToChar(OopType oop);✓ OopType GciTsCharToOop(uint ch);✓ OopType GciTsDoubleToSmallDouble(double aFloat);✓ OopType GciI32ToOop(int arg);✓ OopType GciTsDoubleToOop(GciSession sess, double aDouble, GciErrSType *err);✓ BoolType GciTsOopToDouble(GciSession sess, OopType oop, ...);✓ OopType GciTsI64ToOop(GciSession sess, int64 arg, GciErrSType *err);✓ BoolType GciTsOopToI64(GciSession sess, OopType oop, int64 *result, GciErrSType *err);
Table 7.8 Object Traversal and Path Functions
int GciTsStoreTravDoTravRefs(GciSession sess, ...);✓ int GciTsFetchTraversal(GciSession sess, ...);✓ BoolType GciTsStoreTrav(GciSession sess, ...);✓ int GciTsMoreTraversal(GciSession sess, ...);
Table 7.9 Structural Access Functions
✓ int64 GciTsFetchBytes(GciSession sess, ...);✓ int64 GciTsFetchChars(GciSession sess, ...);✓ int64 GciTsFetchUtf8Bytes(GciSession sess, ...);✓ BoolType GciTsStoreBytes(GciSession sess, ...);✓ int GciTsFetchOops(GciSession sess, ...);✓ BoolType GciTsStoreOops(GciSession sess, ...);✓ int GciTsRemoveOopsFromNsc(GciSession sess, ...);✓ int64 GciTsFetchObjInfo(GciSession sess, OopType objId, ...);✓ int64 GciTsFetchSize(GciSession sess, OopType obj, GciErrSType *err);✓ int64 GciTsFetchVaryingSize(GciSession sess, OopType obj, GciErrSType *err);✓ OopType GciTsFetchClass(GciSession sess, OopType obj, GciErrSType *err);✓ int GciTsIsKindOf(GciSession sess, ...);✓ int GciTsIsSubclassOf(GciSession sess, ...);✓ int GciTsIsKindOfClass(GciSession sess, ...);✓ int GciTsIsSubclassOfClass(GciSession sess, ...);✓ BoolType GciTsObjExists(GciSession sess, OopType obj);
Table 7.10 Utility Functions
✓ uint GciTsVersion(char *buf, size_t bufSize); int GciTsWaitForEvent(GciSession sess, int latencyMs, ...); BoolType GciTsCancelWaitForEvent(GciSession sess, GciErrSType *err);
Other Functions
Fork
GciTs offers a variety of Fork
functions that take a callback. But since node-ffi
supports async library calls, we don't need to do it ourselves.
BoolType GciTsForkLogin(...); BoolType GciTsForkContinueWith(GciSession sess, ...); BoolType GciTsForkExecute(GciSession sess, ...); BoolType GciTsForkPerform(GciSession sess, ...); BoolType GciTsForkStoreTravDoTravRefs(GciSession sess, ...);
String
The following are deprecated in favor of the underscore version.
OopType GciTsNewString(GciSession sess, ...); OopType GciTsNewUnicodeString(GciSession sess, ...); OopType GciTsNewUtf8String(GciSession sess, ...);
The following provide UTF-8 conversion that can be done in JavaScript.
BoolType GciUtf8To8bit(const char* src, char *dest, ssize_t destSize); ssize_t GciNextUtf8Character(const char* src, size_t len, uint *chOut);
GCI Errors
The following do not seem to work.
BoolType GciTsClassRemoveAllMethods(GciSession sess, ...); int64 GciTsFetchUtf8(GciSession sess, ...);