Re: Can Jscript source code be visible in a browser?



> if you had done web application development at all, you
> would know what I suggested is not far from the answer. Moreover, if
> you take a look at the JavaScript source of relatively big web sites
> like MSN or Amazon, their JavaScripts are obfuscated. That's at least
> what we can do as web developers to hide JavaScript.

I can't help but step in here. I've done *lots* of web development.

The fact that *you* can't read the JavaScript on the MSN or Amazon web sites
doesn't mean it's obfuscated. But just to be sure, let's have a look at the
Amazon.com home page:

<script language="Javascript1.1" type="text/javascript">
<!--
function amz_js_PopWin(url,name,options){
var ContextWindow = window.open(url,name,options);
ContextWindow.opener = this;
ContextWindow.focus();
}
function amz_js_RefreshOriginalWindow(url) {
if ((window.opener == null) || (window.opener.closed))
{
var OriginalWindow = window.open(url);
OriginalWindow.opener = this;
}
else{
window.opener.location=url;
}
}
//-->
<script language="JavaScript1.2" type="text/javascript"
src="http://g-images.amazon.com/images/G/01/nav2/prod/n2BootstrapLibs/n2BootstrapLibs-azbTbs-42329.js";
></script>
<script language="javascript1.2">
//n2RunIfLoaded('simplePopover', function() {
n2RunThisWhen('onload', function () {
goGoldboxPop = new N2SimplePopover();
goN2Events.registerFeature('goldboxPop', 'goGoldboxPop',
'n2MouseOverHotspot', 'n2MouseOutHotspot');
goGoldboxPop.initialize('goldboxPopDiv', 'goGoldboxPop');
}, 'init popover' );
</script>
<script language="javascript" type="text/javascript">//<![CDATA[
function submitSearch(form) {
var value = form.q.value;
if (value) {
if (value == "robots.txt" || value == "favicon.ico") {
value = '"' + value + '"';
}
if (typeof(encodeURIComponent) != "undefined") {
value = encodeURIComponent(value);
} else {
value = escape(value);
}
location.href = "http://a9.amazon.com/?dns=www&src=amz&qs="; + value;
}
return false;
}
//]]</script>
<script language="javascript" type="text/javascript">//<![CDATA[
n2RunThisWhen(n2sRTWTBS,
function() {
SimplePop = new N2SimplePopover();
// register you popup feature with the events framework
goN2Events.registerFeature('findGift', // the feature ID used in the NAME=
'SimplePop', // the object that will act upon the event
'n2MouseOverHotspot', // an events helper function for MouseOver event
'n2MouseOutHotspot'); // an events helper function for MouseOut event
SimplePop.initialize('SimplePopDiv', // the name for your popup DIV. any
unique name will do
'SimplePop', // the object you made up above
gaTD, // the data array (not used here)
null
);
},
'init popover' );
//]]</script>
<script language="JavaScript" type="text/JavaScript">
if (Math.random() < 0.5 ) {
if (Math.random() < 0.5 ) {
document.write('<img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_1.gif";
width="380" vspace="0" usemap="#map1" alt="Holiday Gift Central" hspace="0"
align="center" height="84" border="0" /><table cellpadding="0"
cellspacing="0" border="0"><tr><td><table cellpadding="0" cellspacing="0"
border="0"><tr><td><a
href="/gp/gift-central/gift-guides/ref=cm_gift_tcg_gg_lp_box"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_gg_2a_heading2.gif";
width="190" vspace="0" alt="Gift Guides" hspace="0" align="center"
height="82" border="0" /></a></td></tr><tr><td><a
href="/gp/gift-central/gift-guides/rc/R3AQAT3935LLJE/ref=cm_gift_tcg_gg_mag_esq"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_gg_2b_esquire.gif";
width="190" vspace="0" alt="Gift ideas from Esquire magazine" hspace="0"
align="center" height="74" border="0"
/></a></td></tr></table></td><td><table cellpadding="0" cellspacing="0"
border="0"><tr><td><a
href="/gp/gift-central/organizer/ref=cm_gift_tcg_organizer_box_top"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_go_3a_top.gif";
width="190" vspace="0" alt="Gift Central Gift Organizer" hspace="0"
align="center" height="82" border="0" /></a></td></tr><tr><td><a
href="/gp/gift-central/organizer/ref=cm_gift_tcg_organizer_box_bot"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_go_3b_btm.gif";
width="190" vspace="0" alt="Gift Central Gift Organizer" hspace="0"
align="center" height="74" border="0"
/></a></td></tr></table></td></tr></table></td></tr></table></div>');
} else {
document.write('<img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_1.gif";
width="380" vspace="0" usemap="#map1" alt="Holiday Gift Central" hspace="0"
align="center" height="84" border="0" /><table cellpadding="0"
cellspacing="0" border="0"><tr><td><table cellpadding="0" cellspacing="0"
border="0"><tr><td><a
href="/gp/gift-central/gift-guides/ref=cm_gift_tcg_gg_lp_box"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_gg_2a_heading2.gif";
width="190" vspace="0" alt="Gift Guides" hspace="0" align="center"
height="82" border="0" /></a></td></tr><tr><td><a
href="/gp/gift-central/gift-guides/rc/R896RIJU0Q7UW/ref=cm_gift_tcg_gg_mag_bon"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_gg_2b_bonappetit.gif";
width="190" vspace="0" alt="Gift ideas from Bon Appetit magazine" hspace="0"
align="center" height="74" border="0"
/></a></td></tr></table></td><td><table cellpadding="0" cellspacing="0"
border="0"><tr><td><a
href="/gp/gift-central/organizer/ref=cm_gift_tcg_organizer_box_top"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_go_3a_top.gif";
width="190" vspace="0" alt="Gift Central Gift Organizer" hspace="0"
align="center" height="82" border="0" /></a></td></tr><tr><td><a
href="/gp/gift-central/organizer/ref=cm_gift_tcg_organizer_box_bot"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_go_3b_btm.gif";
width="190" vspace="0" alt="Gift Central Gift Organizer" hspace="0"
align="center" height="74" border="0"
/></a></td></tr></table></td></tr></table></td></tr></table></div>');
}
} else {
if (Math.random() < 0.5 ) {
document.write('<img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_1.gif";
width="380" vspace="0" usemap="#map1" alt="Holiday Gift Central" hspace="0"
align="center" height="84" border="0" /><table cellpadding="0"
cellspacing="0" border="0"><tr><td><table cellpadding="0" cellspacing="0"
border="0"><tr><td><a
href="/gp/gift-central/gift-guides/ref=cm_gift_tcg_gg_lp_box"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_gg_2a_heading2.gif";
width="190" vspace="0" alt="Gift Guides" hspace="0" align="center"
height="82" border="0" /></a></td></tr><tr><td><a
href="/gp/gift-central/gift-guides/rc/R3AQAT3935LLJE/ref=cm_gift_tcg_gg_mag_esq"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_gg_2b_esquire.gif";
width="190" vspace="0" alt="Gift ideas from Esquire magazine" hspace="0"
align="center" height="74" border="0"
/></a></td></tr></table></td><td><table cellpadding="0" cellspacing="0"
border="0"><tr><td><a
href="/gp/gift-central/today/ref=cm_gift_tcg_today_box_top"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_tg_3a_top.gif";
width="190" vspace="0" alt="Today.s Gift" hspace="0" align="center"
height="82" border="0" /></a></td></tr><tr><td><a
href="/gp/gift-central/today/ref=cm_gift_tcg_today_box_bot"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_tg_3b_btm.gif";
width="190" vspace="0" alt="Today.s Gift" hspace="0" align="center"
height="74" border="0"
/></a></td></tr></table></td></tr></table></td></tr></table></div>');
} else {
document.write('<img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_1.gif";
width="380" vspace="0" usemap="#map1" alt="Holiday Gift Central" hspace="0"
align="center" height="84" border="0" /><table cellpadding="0"
cellspacing="0" border="0"><tr><td><table cellpadding="0" cellspacing="0"
border="0"><tr><td><a
href="/gp/gift-central/gift-guides/ref=cm_gift_tcg_gg_lp_box"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_gg_2a_heading2.gif";
width="190" vspace="0" alt="Gift Guides" hspace="0" align="center"
height="82" border="0" /></a></td></tr><tr><td><a
href="/gp/gift-central/gift-guides/rc/R896RIJU0Q7UW/ref=cm_gift_tcg_gg_mag_bon"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_gg_2b_bonappetit.gif";
width="190" vspace="0" alt="Gift ideas from Bon Appetit magazine" hspace="0"
align="center" height="74" border="0"
/></a></td></tr></table></td><td><table cellpadding="0" cellspacing="0"
border="0"><tr><td><a
href="/gp/gift-central/today/ref=cm_gift_tcg_today_box_top"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_tg_3a_top.gif";
width="190" vspace="0" alt="Today.s Gift" hspace="0" align="center"
height="82" border="0" /></a></td></tr><tr><td><a
href="/gp/gift-central/today/ref=cm_gift_tcg_today_box_bot"><img
src="http://g-images.amazon.com/images/G/01/gifts/giftcentral/gateway/gc_gw_tg_3b_btm.gif";
width="190" vspace="0" alt="Today.s Gift" hspace="0" align="center"
height="74" border="0"
/></a></td></tr></table></td></tr></table></td></tr></table></div>');
}
}
</script>
<script language="JavaScript1.1" type="text/javascript">
<!--
var agt=navigator.userAgent.toLowerCase();
var is_major = parseInt(navigator.appVersion);
var is_nav = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
&& (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
&& (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));
var is_gecko = (agt.indexOf('gecko') != -1);
var is_ie = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
var is_aol = (agt.indexOf("aol") != -1);
var is_opera = (agt.indexOf("opera") != -1);
var is_win = ( (agt.indexOf("win")!=-1) || (agt.indexOf("16bit")!=-1) );
//-->
</script>
<script language="JavaScript1.1" type="text/javascript">
<!--
var OpenedWin;
function openWin (URL, width, height) {
OpenedWin = window.open(URL, "demo_window",
"width="+width+",height="+height+",status=no,menubar=no,location=no,toolbar=no,directories=no,scrollbars=no");
if (! is_aol) {
var NewX = (screen.availWidth/2)-(width/2);
var NewY = (screen.availHeight/2)-(height/2);
OpenedWin.moveTo(NewX, NewY);
NewX = null;
NewY = null;
}
}
function launch (URL, width, height) {
if (!URL || !width || !height) {
alert("Error");
} else if (width>screen.availWidth || height>screen.availHeight) {
var message;
message = "Your screen resolution is too low to display the demo.\nClick
'OK' if you wish to continue anyway.\n";
message += '\n Your screen resolution: '+screen.width+' x '+screen.height;
message += ' | Viewable: '+screen.availWidth+' x '+screen.availHeight;
message += '\n Required: '+width+' x '+height;
if (confirm(message)) {
message = "If you can not find the close buttons, use your keyboard:\n";
message += 'Windows: ALT+F4\n';
message += 'Macintosh: COMMAND+W';
alert(message);
openWin(URL, width, height);
}
} else {
openWin(URL, width, height);
}
}
function displayLink(text){
if ( is_major >= 4 && is_win && ( is_nav || is_ie || is_opera ||
is_gecko ) ) {
document.write(text);
};
}
//-->
</script>
<script language="JavaScript1.1" type="text/javascript">
<!--
//-->
</script>
<script language="JavaScript1.1" type="text/javascript">
<!--
//-->
</script>
<script language="Javascript1.1" type="text/javascript">
<!--
top.focus();
//-->
</script>

That's it. Not much obfuscation there....

Oh, yeah. There *is* that external JavaScript. Darned if I opened up my
Temporary Internet Files folder and couldn't find it. Pretty darned clever
of them!

So, I just typed the URL into my browser, and was prompted to run or save
the script file. I saved it, opened it in NotePad, and here it is:

//! ################################################################
//! This file contains both original and merged/adapted code .
//! Except where indicated, all code is
//! Copyright (c) 2004 Amazon.com, Inc., and its Affiliates.
//! All Rights Reserved.
//! Not to be reused without permission
//! $Change$
//! $Revision$
//! $DateTime$
var gbN2LibMonMigrated = true;
var N2Loaded = false;
var n2LMStart = new Date();
var gaN2CSSLibs = new Array();
var gaN2JSLibs = new Array();
var oTheDoc = document;
var oTheBody = oTheDoc.body;
var oTheHead = document.getElementsByTagName('head').item(0);
var n2sRTW1='onload';
var n2sRTWTBS='simplepopoverloaded';
function N2Initializer () {
this.aHandlers = new Array();
this.aEventsRun = new Array();
this.bCoreLoaded = false;
}
new N2Initializer ();
N2Initializer.prototype.runThisWhen = function (sWhen, fFn, sComment) {
if ( (typeof fFn != 'function') || fFn == null) return false;
sWhen = sWhen.toLowerCase();
if ( (sWhen =='inbody' && document.body) || this.aEventsRun[sWhen] ){
fFn();
} else {
this.aHandlers[this.aHandlers.length] = { sWhen: sWhen, fFn: fFn, sComment:
sComment };
}
return true
}
N2Initializer.prototype.initializeThis = N2Initializer.prototype.runThisWhen
N2Initializer.prototype.loadThisWhen = function (sWhen, sURL, sID,
sComment) {
sWhen = sWhen.toLowerCase();
goN2LibMon.monitorLoad (sID);
if ( sWhen =='now' ) {
n2LoadScript(sURL, true, sID);
} else {
this.aHandlers[this.aHandlers.length] = { sWhen: sWhen, sURL: sURL, sID:
sID, sComment: sComment };
}
return true
}
N2Initializer.prototype.run = function (sWhen) {
sWhen = (typeof sWhen == 'undefined') ? null : sWhen;
sWhen = sWhen.toLowerCase();
this.aEventsRun[sWhen] = true;
if (sWhen == 'coreloaded') { this.bCoreLoaded=true; }
if (window.goN2Debug) goN2Debug.info("N2Initializer called with " + (sWhen ?
"'"+sWhen+"'" : "null"));
var aH = this.aHandlers;
var len = aH.length;
for (var i=0;i<len;i++) {
var oTmp = aH[i];
if ((oTmp.bCalled != true) &&
(oTmp.fFn || oTmp.sURL) &&
( (sWhen == null) || (oTmp.sWhen && (oTmp.sWhen == sWhen)))
) {
if ((oTmp.sWhen == 'coreloaded') && !this.bCoreLoaded) continue;
if (window.goN2Debug) ;
if (oTmp.fFn) {
oTmp.fFn();
} else if (oTmp.sURL) {
n2LoadScript(oTmp.sURL, true, oTmp.sID);
}
oTmp.bCalled = true;
}
}
}
goN2Initializer = new N2Initializer();
function n2RunThisWhen (sWhen, fFn, sComment) {
goN2Initializer.runThisWhen(sWhen, fFn, sComment);
}
function n2LoadThisWhen (sWhen, sURL, sID, sComment) {
goN2Initializer.loadThisWhen(sWhen, sURL, sID, sComment);
}
function n2RunIfLoaded (sLibID, fFn, sComment) {
n2RunThisWhen(sLibID+'loaded', fFn, 'sequenced init of '+ sComment);
}
function n2LoadScript (sURL, bLocalCacheOK, sLibID) {
if (sLibID) { goN2LibMon.requestLoad (sLibID); }
var e = oTheDoc.createElement("script");
e.type="text/javascript";
if (bLocalCacheOK) {
e.src = sURL;
} else {
e.src = sURL + (sURL.indexOf('?') == -1 ? '?' : '&') + 'lt='+ new
Date().getTime();
}
oTheHead.appendChild(e);
}
function N2LibraryMonitor() {
this.aLibs = {};
this.bJSLoaded=false;
this.bCSSLoaded=false;
this.sNotLoaded ='A desirable part of the page did not load. Please refresh
the page to try again. \n';
this.nTimer=null;
this.nTimeoutMs = 10000;
}
new N2LibraryMonitor();
N2LibraryMonitorProto = N2LibraryMonitor.prototype;
N2LibraryMonitor.prototype.monitorLoad = function (sLibID) {
this.aLibs[sLibID] = { sID: sLibID, nDuration: -1 };
}
N2LibraryMonitor.prototype.requestLoad = function (sLibID, sFeatureID) {
var oTmp = this.aLibs[sLibID];
if (oTmp) { oTmp.nDuration= -2; }
this.resetTimer();
}
N2LibraryMonitor.prototype.beginLoad = function (sLibID, sFeatureID) {
var oTmp = this.aLibs[sLibID];
if (oTmp) {
oTmp.sFeature = sFeatureID;
oTmp.nBegin = new Date().getTime();
oTmp.nDuration= -3;
}
};
N2LibraryMonitor.prototype.endLoad = function (sLibID, nStatus) {
var oTmp = this.aLibs[sLibID];
if (oTmp) { oTmp.nDuration = new Date().getTime() - oTmp.nBegin;
oTmp.bLoaded=true;}
var bALL;
if (bALL=this.allLibsLoaded()) {
this.clearTimer();
} else {
this.resetTimer();
}
goN2Initializer.run(sLibID+'loaded');
if (bALL) {
goN2Initializer.run('lastlibraryloaded');
}
}
N2LibraryMonitorProto.clearTimer=function() {
if (this.nTimer) {
clearTimeout(this.nTimer);
this.nTimer = null;
}
}
N2LibraryMonitorProto.resetTimer=function() {
if (this.nTimer) {
clearTimeout(this.nTimer); }
this.nTimer = setTimeout(n2LibraryLoadTimeout, this.nTimeoutMs);
}
function n2LibraryLoadTimeout() {
goN2Initializer.run('libraryloadfailed');
}
N2LibraryMonitor.prototype.allLibsLoaded = function () {
var bAllLoaded=true;
for (var key in this.aLibs) {
if (this.aLibs[key] && this.aLibs[key].nDuration <0) { bAllLoaded=false; }
}
this.bJSLoaded = bAllLoaded;
return bAllLoaded;
}
N2LibraryMonitor.prototype.confirmJSLoaded = function() { return
this.bJSLoaded; }
N2LibraryMonitor.prototype.confirmCSSLoaded = function() {
this.bCSSLoaded=true; }
N2LibraryMonitor.prototype.isJSLoaded = function() { return
this.bJSLoaded; }
N2LibraryMonitor.prototype.isCSSLoaded = function() { return
this.bCSSLoaded; }
N2LibraryMonitor.prototype.status = function() {
if (this.bJSLoaded) return "OK!";
else return this.sNotLoaded;
}
N2LibraryMonitor.prototype.stats = function() { return "N/A"; };
goN2LibMon = new N2LibraryMonitor();
var n2LLStop = new Date();
var n2LMStop = new Date();
function N2ConfigBase() {
this.getValue = function(id,d) {
if(typeof this[id] != 'undefined') { return this.id; }
else { return d; } } }
var goN2ConfigBase = new N2ConfigBase();
document.write('<link
href="http://g-images.amazon.com/images/G/01/nav2/prod/n2CoreCSS/n2CoreCSS-n2v1-4580.css";
type="text/css" rel="stylesheet">'+
'');
goN2LibMon.monitorLoad ("utilities");
goN2LibMon.monitorLoad ("events");
goN2LibMon.monitorLoad ("simplePopover");
document.write('<script language="javascript"
src="http://g-images.amazon.com/images/G/01/nav2/prod/n2CoreLibs/n2CoreLibs-utilities-19637.js";
type="text/javascript"></script><\/script>'+
'<script language="javascript"
src="http://g-images.amazon.com/images/G/01/nav2/prod/n2CoreLibs/n2CoreLibs-events-63727.js";
type="text/javascript"></script><\/script>'+
'<script language="javascript"
src="http://g-images.amazon.com/images/G/01/nav2/prod/n2CoreLibs/n2CoreLibs-simplePopover-18851.js";
type="text/javascript"></script><\/script>'+
'');
var goCust = new Object();
goCust.isLoggedIn=function() { return false; }
var goN2Explorer;
var gaTD;
var goN2AC;
n2RunThisWhen (n2sRTWTBS,
function() {
oAllCatPopover = new N2SimplePopover();
goN2Events.registerFeature('two-tabs', 'oAllCatPopover',
'n2MouseOverHotspot', 'n2MouseOutHotspot');
goN2Events.setFeatureDelays('two-tabs',200, 400, 200);
oAllCatPopover.initialize('AllCatPopoverDiv',
'oAllCatPopover',null,null,'below','c');
},
'All Categories popover');
n2RunThisWhen(n2sRTW1,
function() {
if (!window.gaTD) gaTD = new Array();
N2Loaded = goN2LibMon.isJSLoaded();
}, "Last Init"
);

So much for obfuscation.

> 1. Use SSL. Although SSL encrypts the HTTP traffic, at least IE doesn't
> seem to cache files like Whatever.js. I haven't tried it with other
> browsers.

SSL will prevent anyone from intercepting and reading a packet on the
network, but it sure won't encrypt anything on the client.

> 2. Call server-side code to using XMLHTTP.

Nope.

Now, if *you* had done *much web* application development at all, you would
realize that the browser has to read this stuff. And the browser is on
*your* computer. Therefore, if the browser can read it, find it, get it, so
can you. All you have to do is what your browser does: Interpret HTML.

The ONLY answer is to use server-side application processing. Anything on
the client is fair game.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
Complex things are made up of
Lots of simple things.

<hiriumi@xxxxxxxxx> wrote in message
news:1131470727.973661.314780@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Hi, Bob.
> Excuse me for not coming up with a way to hide JavaScript on the client
> side.
>
>> Both of your suggestions are comparable to leaving your house unlocked,
>> and taping a note on the front door saying that the door is locked.
>
> Your analogy against my suggestion doesn't seem to be correct. Web
> developers are not telling end users that JavaScripts sources are
> available, and if you had done web application development at all, you
> would know what I suggested is not far from the answer. Moreover, if
> you take a look at the JavaScript source of relatively big web sites
> like MSN or Amazon, their JavaScripts are obfuscated. That's at least
> what we can do as web developers to hide JavaScript. Like Andrew
> suggested in this thread, if you don't want to expose your code, you'd
> have to do it on the server side. I only suggested the two possible
> ways to hide JavaScript in addition to what others suggested here.
>
> Putting that aside, if I may, I could suggest two more ways to possibly
> hide important logic from the client side.
>
> 1. Use SSL. Although SSL encrypts the HTTP traffic, at least IE doesn't
> seem to cache files like Whatever.js. I haven't tried it with other
> browsers.
>
> 2. Call server-side code to using XMLHTTP.
>
> I guess there isn't really a perfect solution for hiding JavaScript.
> The ideal solution would be to entirely encrypt JavaScript, but then,
> browsers would have to support such technology. It doesn't seem to
> exist today.
>


.