Why do I get no warning when protocol methods are not specified? - warnings

I'm using Xcode 4, have a simple class interface defined and I added NSTableViewDelegate and NSTableViewDataSource protocols to the interface definition. I.e,
#interface foo : NSObject < NSTableViewDelegate, NSTableViewDataSource>
In my build settings, I have confirmed that the option "Incomplete Objective-C Protocols" warning is enabled (for Debug/Any Architecture etc) and I should get a compile time warning for the non-optional methods required for the NSTableViewDataSource protocol. However, I get no warnings at all but then at runtime I see the message in the log that the methods aren't defined.
Anyone know why?

If you look at Apple's NSTableView.h, you'll se this:
#protocol NSTableViewDataSource <NSObject>
#optional
/* Required Methods
*/
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView;
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)ta bleColumn row:(NSInteger)row;
...
So the comment and the documentation claim that the methods are required, but the code says they're not. The compiler ultimately ignores all comments and documentation happily altogether. ;) Hence you're not getting a compiler warning.
I guess it was their intention to make these two methods required (would make lots of sense), but discovered that lots of their own code relies on it being an informal protocol still. So instead of the headache of changing all the legacy code, I assume they decided to not make them required just yet. I'd expect this to change in Lion though.

Related

Debugging experimental WebAssembly externref bug in Google Chrome

Warning: as the reference types proposal isn't complete yet, this code will not run without toggling flags or setting in order to enable executing experimental code.
If you are on Google Chrome or a Chromium browser, you will need to enable the following flag:
chrome://flags/#enable-experimental-webassembly-features
I had set up a simple handwritten Wasm module for personal use. I could've easily written it in JavaScript, but it was easier and made more sense to use Wasm, and since it was a simple, personal script, I wouldn't care if other people couldn't run it.
I had compiled it using wabt's wat2wasm.
The Wasm module was intended to be fed the entire globalThis object to import from.
From there, it took four TypedArray constructors: Uint8Array, Uint16Array, Uint32Array, and BigUint64Array.
Take note: no code was executed prior to the Wasm, thus there cannot be any interference.
Later, I had realized that that the Wasm wasn't working as intended at all, my math was correct, but the variables were wrong.
I had narrowed my problem down to just this:
;; global -> global variable
(import "globalThis" "Uint8Array" (global $Uint8Array externref))
(import "globalThis" "Uint16Array" (global $Uint16Array externref))
(import "globalThis" "Uint32Array" (global $Uint32Array externref))
(import "globalThis" "BigUint64Array" (global $BigUint64Array externref))
;; func -> function
(import "console" "log" (func $console::log (param externref)))
(start $_start)
(func $_start
global.get $Uint8Array
call $console::log
global.get $Uint16Array
call $console::log
global.get $Uint32Array
call $console::log
global.get $BigUint64Array
call $console::log
)
This Wasm was instantiated like so:
WebAssembly.instantiateStreaming(
fetch(
"test.wasm", {
mode : "same-origin",
credentials : "omit",
cache : "no-store",
redirect : "error",
referrer : "no-referrer"
}
), globalThis
).catch( console.error );
The interesting problem is that the logs all say the same thing: Uint8Array.
I was dumbfounded. This has to be literally impossible. The JavaScript file itself was not cached, the WebAssembly was being fetched with "no-cache," the web page itself wasn't cached.
Then I thought, because I was using XHTML, maybe it didn't happen in HTML files. It did there too.
I tried converting the Wasm file to a TypedArray and just using WebAssembly.instantiate, suddenly, it worked flawlessly.
At this point the server must be serving the wrong file, because the further I go, the more this seems like nonsense.
I almost want to say that this is a Chromium browser or V8 runtime error, but I need to narrow it down a bit more before I blindly attempt to present this as a bug.
I have set up two different versions of the same code, on Repl.it, and on CodeSandBox.io, so that hopefully someone can try running it themself, to confirm the bug, and maybe attempt to debug where I went wrong.
(Could this be a problem with Repl.it's server?)
This was a compiler bug fixed by Chromium in
https://chromium-review.googlesource.com/c/v8/v8/+/2551100.
This was the response that I had gotten from one of the developers:
This is indeed a timing issue that has been fixed in https://chromium-review.googlesource.com/c/v8/v8/+/2551100. The problem happens when there are only imported globals, and compilation of the WebAssembly functions finishes before the stream actually finishes. In this case, the offset calculation happens after the compiler uses the offsets, and therefore produces incorrect code.
A workaround is to define one global that is not imported, as this causes the offset calculation to happen earlier.
Seems like sending a small module that only imports globals instead of functions was breaking the code.
Their code had a threading race condition between the stream and the compiler.

Is there a way to force the UWP RichEditBox use only UTF encoding when the user types?

I am trying to convert the contents of a UWP RichEditBox to HTML.
For that purpose, I've tried using the RtfPipe library (https://github.com/erdomke/RtfPipe). From the looks of it, this library has a problem on UWP, due to the fact that not all encodings are defined on that target framework. (This is the error you get, if you are interested: Encoding.GetEncoding can't work in UWP app, but the accepted answer seems not to be the best option on all platforms - I haven't even managed to make the suggested fix compile, so it might not be valid anymore)
Now, as a way of avoiding this from happening, I am wondering whether there is a way to force the control to always use one of the UWP-defined UTF-variants for encoding the data when the user types his text.
Because, now, when I type into it, I get things like that:
{\rtf1\fbidis\ansi\ansicpg1253\deff0\nouicompat\deflang1032{
....
\pard\tx720\cf1\f0\fs23\lang1033
...that make the library throw exceptions.
I guess, if I manage to make it not use ASCII code pages, things will be great.
After taking a look at the control properties though, I do not see something I could use. Is there any way to achieve this?
This is the error you get, if you are interested: Encoding.GetEncoding can't work in UWP app
As you described, there is an inner error thrown when using this package with UWP app. System.ArgumentException: 'Windows-1252' is not a supported encoding name, by testing on my side, which is thrown by the code line public static readonly Encoding AnsiEncoding = Encoding.GetEncoding("Windows-1252"); of RtfSpec.cs when UpdateEncoding.
It seems like Windows-1252 may not be supported in UWP from the error details,also see this similar thread. You could use UTF instead as you want, for example, have a change on the library with following then it will work (testing demo here).
public static readonly Encoding AnsiEncoding = Encoding.UTF8;
I haven't even managed to make the suggested fix compile, so it might not be valid anymore
Encoding.RegisterProvider method should be work, but it only support UWP or .NET Framework 4.6, it does't support the Portable Class Library. The RtfPipe library you mentioned is Portable Class Library, so that you cannot use Encoding.RegisterProvider. Encoding.GetEncoding method supports Portable Class Library, details please check the version information of the two classed.
I guess, if I manage to make it not use ASCII code pages
RTF itself uses the ANSI, PC-8, Macintosh, or IBM PC character set to control the representation and formatting of a document, you may not able to change that. Consider to update the library to resolve the issue for UWP.

How do I avoid conflicts between haxe Type class and C# Type class?

I am developing Haxe code that I convert in C# and insert into a Unity project.
The conversion works fine and I am able to use the generated class when I import it alone in Unity.
To make it work, I have to bring in Unity the whole generated src folder, including the Type.cs file.
However, when I import the "Post Processing Stack" (a basic Unity extension) I get errors due to name Conflicts. The Type class is also a basic C# class and It is used by the Post Processing scripts.
The haxe-Type takes priority and breaks the compilation:
Assets/PostProcessing/Runtime/PostProcessingBehaviour.cs(406,30): error CS1502: The best overloaded method match for `System.Collections.Generic.Dictionary<Type,System.Collections.Generic.KeyValuePair<UnityEngine.Rendering.CameraEvent,UnityEngine.Rendering.CommandBuffer>>.Add(Type, System.Collections.Generic.KeyValuePair<UnityEngine.Rendering.CameraEvent,UnityEngine.Rendering.CommandBuffer>)' has some invalid arguments
Assets/PostProcessing/Runtime/PostProcessingBehaviour.cs(406,34): error CS1503: Argument `#1' cannot convert `System.Type' expression to type `Type'
I don't know if it is possible to solve this issue by playing around with C#/Unity/Mono search paths.
I as wondering wether it is more appropriate to (optionally) wrap all haxe top-level classes into the haxe namespace, or a special haxe-defaultnamespace, or prefix them for example to class HType.
Name conflicts for this basic types are likely to emerge in many other contexts, not only in Unity.
I found the solution in the Haxe documentation for C#:
https://github.com/HaxeFoundation/HaxeManual/wiki/Haxe-C%23
-D no-root generate package-less haxe types in the haxe.root namespace to avoid conflicts with other types in the root namespace
This way, all the classes that were at global level will be generated under namespace haxe.root.

Grails JSON marhsaling using introspection causes severe bottleneck on Classloader.loadClass()

I am using Grails 2.2.4 and have a controller endpoint which converts a domain object list to JSON. Under load (as little as 5 concurrent requests) the marshaling performance is very poor. Taking thread dumps the threads are blocked on:
java.lang.ClassLoader.loadClass(ClassLoader.java:291)
There is a single marhsaler registered to marshal all domain objects using reflection and introspection. Realizing that reflection and introspection is slower than direct method calls, I am still seeing unexpected behavior in that the class loader is caller every time and in turn blocking occurs. An example stacktrace is as follows:
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.ClassLoader.loadClass(ClassLoader.java:291)
- waiting to lock <785e31830> (a org.grails.plugins.tomcat.ParentDelegatingClassLoader)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.beans.Introspector.instantiate(Introspector.java:1470)
at java.beans.Introspector.findExplicitBeanInfo(Introspector.java:431)
at java.beans.Introspector.<init>(Introspector.java:380)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at org.springframework.beans.CachedIntrospectionResults.<init>(CachedIntrospectionResults.java:217)
at org.springframework.beans.CachedIntrospectionResults.forClass(CachedIntrospectionResults.java:149)
at org.springframework.beans.BeanWrapperImpl.getCachedIntrospectionResults(BeanWrapperImpl.java:324)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:727)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:721)
at org.springframework.beans.PropertyAccessor$getPropertyValue.call(Unknown Source)
at com.ngs.id.RestDomainClassMarshaller.extractValue(RestDomainClassMarshaller.groovy:203)
...
...
A simple benchmark loading the same endpoint with the same parameters results in the loadClass call.
I was under the impression the classes would be at least cached by the class loader and not loaded on every method call to get the property to be marshaled.
The code to retrieve the property value is as follows:
BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(domainObject);
return beanWrapper.getPropertyValue(property.getName());
Is there a configuration setting that is needed to ensure the classes are only loaded once? or perhaps a different way to get the property that doesn't result in class loading every time? Or perhaps a more performant way to achieve this?
Writing a custom marshaler per domain class would avoid the reflection and introspection but is going to be a lot of repeat code.
Appreciate any input.
So after much digging this is what I found out.
Using the BeanUtils.getPropertyDescriptors and getValue will always try and find a BeanInfo class describing the bean using the class loader. In this case we don't provide BeanInfo classes for our grails domain classes so this call is redundant. I found some information where you can provide a custom BeanInfoFactory to bypass this and exclude your packages but I couldn't find how to configure it with Grails.
Also searching the springframework documentation there is a configuration option you can pass Introspector.IGNORE_ALL_BEANINFO that will tell CachedIntorspectionResults to never look up the bean classes. However this was not available in version 3.1.4 of springframework which was current for grails 2.2.4. The newer versions do appear to have this option.
So, if using BeanUtils you can't by pass this initial lookup on the class loader. However subsequent loaders should be cached by CachedIntrospectionResults. Unfortunately this doesn't happen in our scenario. There looks to be a bug in the test to see if the lookup is cacheable. See more info on this below.
The fix was ultimately to fall back to use pure reflection. Rather than use:
beanWrapper.getPropertyValue(property.getName());
To use:
PropertyDescription pd = BeanUtils.getPropertyDescriptor(domainObject.getClass(), property.getName())
pd.readMethod.invoke(domainObject)
Where the pd is cached.
After fixing this the profiler still showed a lack of caching on CachedIntorspectionResults for the out of the box grails marshaller. This was due to the bad caching implementation in CachedIntrospectionResults. The work around for this was to add the correct class loader to the acceptedClassLoaders in the CachedIntrospectionResults.
public class EnhanceCachedIntrospectionResultsAcceptedClassLoadersListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
CachedIntrospectionResults.acceptClassLoader(Thread.currentThread().getContextClassLoader().getParent());
}
public void contextDestroyed(ServletContextEvent event) {
CachedIntrospectionResults.clearClassLoader(Thread.currentThread().getContextClassLoader().getParent());
Introspector.flushCaches();
}
}
Note that it was required to add the parent to the accepted class loader list rather than the current class loader. Not sure if this is specific to grails or not but this fixed the issue. I'm not sure if there may be a side effect to this fix.
In summary we went from 10 requests/sec in the original setup to 120 requests/sec after using direct reflection and fixing the CachedIntrospectionResults cache.
However the real eye opened was that if we use a 1-1 marshaller per domain class we were seeing another x2 improvement in performance over the generic marshaller where we test objects for whether they're instances of class etc. We're saving a lot of code with the generic marshaller but there's a lot more work to do to get comparable performance to writing a 1-1 marshaller.
Hopefully this will be useful to someone else who runs into this ...

Why do I get no warning when protocol methods are not specified?

Merged with Why do I get no warning when protocol methods are not specified?.
I'm using Xcode 4, have a simple class interface defined and I added NSTableViewDelegate and NSTableViewDataSource protocols to the interface definition. I.e,
#interface foo : NSObject < NSTableViewDelegate, NSTableViewDataSource>
In my build settings, I have confirmed that the option "Incomplete Objective-C Protocols" warning is enabled (for Debug/Any Architecture etc) and I should get a compile time warning for the non-optional methods required for the NSTableViewDataSource protocol. However, I get no warnings at all but then at runtime I see the message in the log that the methods aren't defined.
Anyone know why?