Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kAi9g-00022A-1f for pljava-dev@arkaria.postgresql.org; Tue, 25 Aug 2020 23:15:04 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kAi9e-0000xK-0f for pljava-dev@arkaria.postgresql.org; Tue, 25 Aug 2020 23:15:02 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kAi9d-0000vm-HD for pljava-dev@lists.postgresql.org; Tue, 25 Aug 2020 23:15:01 +0000 Received: from anastigmatix.net ([68.171.219.55]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kAi9a-0000z6-Ox for pljava-dev@lists.postgresql.org; Tue, 25 Aug 2020 23:15:01 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=anastigmatix.net; s=default; h=Content-Transfer-Encoding:Content-Type: In-Reply-To:MIME-Version:Date:Message-ID:From:Cc:References:To:Subject:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=zWjzAC7OMPSweTu0aABEkEYkDjKDItjxXkxcMbQ/1RE=; b=WEcZuCdkbnTJnnndIkudi5NMsP n1AOOs3Pxjq5viwvbGZxpqvlOIBFifF+uYzm2WRlj1VV6avYntt42/TlWSUezciCEggCpuiW53fzq lHRZ/j5im1kpvqhYuT+DIUvalkOfhO0w4QuXBPdekXW1ZGiPo5TpoPeFCZsyKTFB8bJvKW9NMwZ7o nqfwjpXyaRWK30fAN84zgaB4FJiZ+wklPe0T2eUlgWWlo6kTG/yYtY/2fYugoNjnIUVWBNnSWE+s9 /UEuBnEpFL3H3PV6zeMq9HrB16Ok2o3B1Fb41yDWWcPA1Lx/ToOLyfP5s/8G3WqV97YqrtepDX00V O3tmCAlw==; Received: from [184.19.31.139] (port=49520) by bay.acenet.us with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.93) (envelope-from ) id 1kAi9X-00Bygt-Gg; Tue, 25 Aug 2020 19:14:56 -0400 Subject: Re: the ScriptingMojo To: Kartik Ohri References: <5F368A99.6070709@anastigmatix.net> <5F36965C.60707@anastigmatix.net> <5F3A7DC6.8090905@anastigmatix.net> <5F3D32E9.80504@anastigmatix.net> <5F3D36BE.70703@anastigmatix.net> <5F3D38F8.7050907@anastigmatix.net> <5F3D3A75.5010304@anastigmatix.net> <5F3D3D2E.4070109@anastigmatix.net> <5F3D43BD.4020900@anastigmatix.net> <5F3DA48D.7090408@anastigmatix.net> <5F41943D.9080707@anastigmatix.net> <5F427604.5010103@anastigmatix.net> <5F42A71F.8000002@anastigmatix.net> Cc: pljava-dev@lists.postgresql.org From: Chapman Flack X-Enigmail-Draft-Status: N1110 Message-ID: <5F459B6E.3020803@anastigmatix.net> Date: Tue, 25 Aug 2020 19:14:54 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-OutGoing-Spam-Status: No, score=-95.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - bay.acenet.us X-AntiAbuse: Original Domain - lists.postgresql.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - anastigmatix.net X-Get-Message-Sender-Via: bay.acenet.us: authenticated_id: chap@anastigmatix.net X-Authenticated-Sender: bay.acenet.us: chap@anastigmatix.net X-Source: X-Source-Args: X-Source-Dir: X-From-Rewrite: unmodified, already matched List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On 08/25/20 17:06, Kartik Ohri wrote: > Hi! > > >> - I don't think formatDefines and formatIncludes make good PGXSUtils >> methods. The syntax could vary across compilers (might it use /D or /I >> on a Windows compiler, for example?). So I think they make better >> AbstractPGXS methods that can be overridden in the configuration. >> There could be a built-in implementation in AbstractPGXS using -D and -I. >> Defines should be provided as a map (key to value) and the option string >> with = sign should be produced by formatting. >> >> Regarding this, it seems that it is not possible to invoke a method whose > implementation > is provided in the Java class before an object is created. (Same for > default methods in an > interface) So, compile itself cannot call a formatDefines if a default > implementation is given using > AbstractPGXS. However, formatDefines can be called separately and the value > be passed to compile. The way I imagined it working, there would be hardly any methods on the JS object that would be expected to be called before using it to instantiate an AbstractPGXS subclass. Only for the probe method did that seem convenient. What I had imagined was a dispatcher that would select one of the JS objects, by calling their probe methods, and then use the selected one to make an AbstractPGXS instance, and call other methods like compile and link on that instance. I've tried the basic idea in nashorn and jshell, like this: jshell> import javax.script.ScriptEngineManager jshell> var sem = new ScriptEngineManager() sem ==> javax.script.ScriptEngineManager@5a5a729f jshell> var se = sem.getEngineByName("javascript") Warning: Nashorn engine is planned to be removed from a future JDK release se ==> jdk.nashorn.api.scripting.NashornScriptEngine@6f6745d6 jshell> public abstract class Foo { public abstract int foo(); public abstract void bar(); public void baz() { System.out.println("Whee!"); } } | created class Foo /* * classes declared in jshell have weird names, so the only way I know to * make Foo known to JS is with these 2 steps a normal class wouldn't need. */ jshell> se.put("FooClass", Foo.class) jshell> se.eval("var Foo = FooClass.static") $6 ==> null jshell> se.eval("var obj = {foo: function(){return 42;}, bar: function(){this.baz();}}") $7 ==> null /* * obj is an ordinary JS object. Its foo method already works. */ jshell> se.eval("obj.foo()") $8 ==> 42 /* * its bar method doesn't, because there's no baz method. */ jshell> se.eval("obj.bar()") | Exception javax.script.ScriptException: TypeError: this.baz is not a function in at line number 1 /* * Now make bigobj be a subclass of Foo, based on obj. */ jshell> se.eval("var bigobj = new Foo(obj)") $10 ==> null jshell> se.eval("bigobj.foo()") $11 ==> 42 jshell> se.eval("bigobj.baz()") Whee! $12 ==> null So that looks like it works ok. One thing I noticed is that bigobj does not keep any JS methods from obj, if they aren't declared in the Java class. So, for example, if I declare the Java class Foo without its foo method, I can still call obj.foo(), but not bigobj.foo(). The adapter magic only exposes the exact API declared by the Java object. But that seems ok. For example, we could leave the probe method undeclared in AbstractPGXS. Every JS recipe would have a probe method, and then when the selected one is used to make a PGXS object, that doesn't have an accessible probe method anymore, which it doesn't need anymore anyway. I have noticed a quirk (in nashorn anyway, haven't tried graal) where even the methods that are declared in the superclass can have trouble referring to each other as this.method() even though calling them from outside as bigobj.method() works fine. The dynamic nature of javascript allows a workaround: they can refer to each other as bigobj.method(). I think that should be workable, as we will only be making one instance of one of these objects, and probably saving that in an outer var, maybe pgxs, and so if its JS-implemented methods internally refer to each other it can just look like methoda: function() { pgxs.methodb(); }. Regards, -Chap