Comments (13)
So yes, I'm still maintaining the project, and will happily review any pull requests.
I'm really glad that you have been working on getting some of these issues fixed, as they've all been on my radar for a long time now, it's just been hard to find the time. Let's get some of these patches landed!
from nodobjc.
Great! We'll clean it up and get it over to you.
from nodobjc.
Hi Nate,
I've finished my own unit tests and have fixed the items below. Can you open a new branch 0.1.0 that I can push up to? There's some issues below that we'd need to address before any sort of merge into a main/master.
Here's the branch: https://github.com/trevorlinton/NodObjC/tree/0.1.0
Changes:
- Decoupled many of the various prototypical inheritances between class/id/etc, the issue was a combination of both garbage collection not properly cleaning up extended classes and there were odd namespacing issues (discussed below) causing corner cases (such as created classes loosing their proto for the class when unwrapping).
- Put all the modules into a tighter closure (except for exception, i can update that though)
- Fixed some garbage collection issues when new function/selector were created, the pointer for the function/selector wasn't held onto, and if the user didn't hold it (but held its container) the GC would gobble it and an Unwrap error occurred.
- Imports now have an optional "recurse" level as a second param to $.Import, cycling recursively through all the imports dependencies can cause a simple nodobjc script to take sometimes 200~300MB. You can now specify a recursion level (0 for just that framework) as a second arg, if none is specified it will default to recursively including all dependences (as before).
- There were circular dependencies that have been fixed (i'm still trying to decouple a handful), these no longer cause GC issues but it may as code increases. Many of the SEL/imp/etc modules were merged together as they took up less memory (~1.2MB) by sitting in core rather than separate modules. The issue was core -> sel -> core -> imp -> core and multiple copies of core and several other modules were being made. Class/ID were converted to using a harder class/prototype schema and seems to have reduced the memory use as well.
- Running a dependency graph there was a lot of proxy/alias function and dead functions in the code (not used by unit tests or examples or I could find in the docs). These were removed, some were commented out and placed at the bottom of the .js files for review. Less code surface, less bugs :)
- The unit tests are not passing, i'm still trying to see what the intent of some of these were as i'm unsure what exactly was trying to be expressed, for example one unit tests creates and instance of a class then does a strict comparison of that class to the instance, failing if they are not equal. Is this supposed to be the case? An instances class definition should be equal to the original class, perhaps an "id instanceof Class" should be, but should a strict equality between instances and classes be true? I'm hoping maybe you can guide me through the failing unit tests and help see what can be done to correct them.
- I added uv.js as a test to see about integrating the CFEventLoop, I have a obj-c .mm file that links with node.js and successfully integrates the app loop with node but the uv.js version (which is pretty damn close) fails.
- I'm also currently working on yanking out libxmljs, the original bridgesupport leaked memory through libxmljs' node object, this has been fixed and drastically reduced memory footprint. There are some quick parsing "hacks" that can be done for parsing xml without having to use libxml. These hacks are fairly fool proof so long as the schema is straight forward, i'm hoping a 0.1.0 version can remove the libxmljs version and hopefully fix up the uv.js CFEventLoop issues.
- Added support for obj-c messages returning structures (specifically struts size >= 16 bytes). This required adding support for objcSendMsgStret (and its super equiv.).
- Changed import/loading system so that it uses the object returned by require for nodobjc to place definitions "onto" rather than using global's. This I thought would be just good practice :/ let me know if it may have screwed something up I didn't realize.
- I don't believe I've integrated the regex types support in index.js. This should also be finished soon.
- Fixed code to support node-ffi 1.2.x
- ref-struct vs. struct and types vs. types collisions, there were instances where Struct was actually ref-struct and not struct.js, i've resolved these as well. I'm unsure if the collisions were causing bugs as most of it was in dead code that was removed.
from nodobjc.
Hey @trevorlinton Nice looking branch, and list! So I've added you as a committer to this main repo. You can push to a new branch if you want and we can take a closer look and get things merged to the master
branch asap.
I really appreciate you diving in and doing what's been on my TODO list for quite a while! Cheers!
from nodobjc.
@TooTallNate Hi Nate, after talking with some Apple engineers the general consensus was that ID's are a nomenclature and that Class and ID effectively mean the same thing since Classes are just Objects in obj-c (but only have significant differences in compiler validations and when integrating with C/C++ bridges). This may actually be good news but brings up a design ramification I wanted to clear through you before I do anything.
Should the ID and Class be merged together? If so, should the following assertions be true:
var someInstance = $.NSString('alloc');
assert(someInstance !== $.NSString);
assert(someInstance instanceof $.NSString);
assert(someInstance instanceof $.NSObject); // maintain heirarchy in obj-c
assert(someInstance.class() === $.NSString);
assert(someInstance.class().super() === $.NSObject);
assert(someInstance.super() == someInstance); // ???????
// what happens here? and instance has a super of what? The NSObject "instance" i suppose?
someInstance.toString(); // Format: '[ '+ClassName+' '+pointerAddress+' ]' [NSString 0x00000003 *]
// note that the * just tries to differentiate between a instance (id) and a class.
someInstance.class().toString(); // [NSString 0x00000001]
someInstance.class().super().toString(); // [NSObject 0x00000000]
someInstance.super().toString(); // [NSObject 0x00000000 *] ????
// what happens here? once again do we infer an "instance" of NSObject as the super? or?
assert(someInstance.isInstance() == true)
assert(someInstance.isClass() == false)
assert($.NSObject.isClass() == true)
assert($.NSObject.class() === Object.prototype) // ???
In addition static or '+' methods are only accessible by Class "definitions" and '-' or instance methods are only available by ID "definitions" (if you will, I say definitions as both Class/ID would come out of the same object in node).
Finally, extending a class simply extends its '+' methods and applies a new inheritance chain? In addition should extending a class into a new one immediately register it within the NodObjc main object for consistency?
from nodobjc.
after talking with some Apple engineers the general consensus was that ID's are a nomenclature and that Class and ID effectively mean the same thing since Classes are just Objects in obj-c.
I mean I wouldn't call them the same thing... Class instances are a type of Object, but vice-versa isn't true. Just look at the Obj-C runtime reference. You can see that there's functions (prefixed class_
) that only work on Class objects, and not instances (which the objc_
prefix is used for). That said... it does still make sense to me to keep them separate. Your ???
assertions below support this (more on that in a sec).
but only have significant differences in compiler validations and when integrating with C/C++ bridges
Well NodObjC is a bridge right? 😉
assertions...
So... all of those assertions seem fine to me in theory, however I'm not sure if we'll be able to get instanceof
working reliably. Setting up an full JS prototype chain of Class objects seems costly to me when all you're really interested in is the base NSString
.
assert(someInstance.super() == someInstance); // ???????
assert(someInstance.super().toString(); // [NSObject 0x00000000 *] ????
// what happens here? once again do we infer an "instance" of NSObject as the super? or?
Both of those bases seem kind of weird to me. A super()
function should probably only be available on Class
objects, not instances.
assert($.NSObject.class() === Object.prototype) // ???
I would think null
actually. Trying to merge over to the JS world once we reach the top of the Obj-C inheritance chain seems unnecessary to me.
extending a class simply extends its '+' methods and applies a new inheritance chain?
Well if we could get instanceof
working like that, then ya, possibly. But we'd still need to do the objc_allocateClassPair()
and friends dance as well, so that the Obj-C runtime registers the subclass as well (what the Class#extend()
function does right now).
In addition should extending a class into a new one immediately register it within the NodObjc main object for consistency?
It already does that in the Class#register()
function. Do you want it to be bound earlier? It's not quite usable/fully subclassed until the register() function is called (objc_registerClassPair()
C function).
Let me know if that helps!
from nodobjc.
@TooTallNate All of your points were fairly spot on. I tried to do some more refactoring but realized I was walking down a rabbit hole and have since stopped.
I have found one issue which is perplexing, using core.objc_getAssociatedObject and core.objc_setAssociatedObject to hold onto a pointer within ID.wrap seems to sometimes cause assertion violations (as the incoming/return pointers are not equal), I believe this is due to the objects original memory pointer being recycled by obj-c's runtime. In addition, it seems it prevents v8 from gobbling up anything passed through ID.wrap, which is obviously an issue. I was wondering if this was done for speed or if it served another purpose? I've also added a test-case memtest.js that tries to cause memory leaks. So far (there's still a ways to go) but it seems most of the memory issues are resolved.
You can see the updates here: trevorlinton@0184e91
Thoughts?
from nodobjc.
IIRC, the core.objc_getAssociatedObject()
and core.objc_setAssociatedObject()
dance was required in order to ensure that a JavaScript wrapper would be the same wrapper instance throughout the Objective-C object's lifetime. See this test case for an example:
NodObjC/test/array-references.js
Line 13 in 938b346
As for your patch, I'll try reviewing that a bit later today. Cheers!
from nodobjc.
@TooTallNate Ahh, that makes more sense, I was shoring up the code to pass all the unit tests and the array-references was one of the outliers I was struggling with. That helps, thanks. I'll soon have a finished patch with all the unit tests passing.
And the latest mem-tests i've ran allocate 2GB of structs, to delegates and function pointers without a single bit of memory leaks! (well, atleast on the javascript/v8 side of things).
from nodobjc.
@TooTallNate All unit tests are passing, memory references seem clear and i've successfully decoupled Class from ID. Note there were minor changes to some unit tests, most were simply changing the "require" file/module; all of the code of the unit tests were kept.
from nodobjc.
@TooTallNate I pushed up branch 0.1.0, docs need to be revised, maybe some more testing and your thumbs up and we can set it in motion!
from nodobjc.
@trevorlinton Hey Trev, so I'm checking out your branch now. First issue is that the dependencies in the package.json
aren't quite right/complete. node-ffi package has been renamed to ffi package (c0aaa30), and there's some additional missing deps.
from nodobjc.
Let's continue this in #39.
from nodobjc.
Related Issues (20)
- Doing an in-app purchase in Electron app for the Mac App Store HOT 1
- [Question] Are there any simple ways to get a binary data of NSData or NSInlineData? HOT 4
- Do I need some release procedure?
- Unable install nodobjc in electron project
- Please update with fixed ffi "callback has been garbage collected" (ffi-napi maybe?) HOT 1
- Activating an application - may be a bug
- can't install nodobjc HOT 2
- Dynamic Linking Error HOT 3
- Question: Any help regarding usage of the NSSharingService (composeEmail)
- Error in electron 3.0.0 HOT 5
- TypeError: error setting argument 2 - writeInt64: Number/String 64-bit value required HOT 2
- Unable to call CoreTextFunctions
- $.import() is not importing nested frameworks
- .EKEventStore
- node event loop blocked whilst menus are active HOT 3
- crashed in electron 4.2.5 HOT 1
- is support Node V12 and electron 5+ HOT 3
- install error
- Question: how to create a NSWindow? HOT 1
- No native build was found for platform=darwin
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nodobjc.