short URL: http://cassisjs.org
Introduction
Conceived in late 2008(1), the goal of the CASSIS Project is universal javascript (JS) that works on the client and the server for scalable application logic. The primary use-case is writing code to implement application logic that runs in browsers, especially dynamic interfaces that make use of XMLHTTPRequest (XHR/AJAX/AHAH), and also runs on web servers.
Until typical hosting companies support running JS on the server, CASSIS code must run in at least two programming language environments, JS on the client, and something that can be made to resemble JS on typical hosting company servers, which turns out to be PHP.
CASSIS stands for: client and server scripting implementation subset.
Summary
live code: https://tantek.com/cassis.js
source code repository: https://github.com/tantek/cassis
updates and news: @cassisjs
CASSIS v0.1 is currently good for: functional programming, math, datetime computations, string processing, parsing, form validation.
License
CassisProject source code (including all examples, fragments, and functions provided below) is licensed under a Creative Commons Attribution Share-Alike license (for now). Please attribute to "Tantek Çelik" and link attribution to https://tantek.com
Including CASSIS
Use the following code to include cassis.js:
Clientside in HTML:
<script type="text/javascript" src="cassis.js"></script>
Serverside in PHP:
ob_start(); // stops the few HTML comments in CASSIS from being outputted
include 'cassis.js';
ob_end_clean();
Implementations using Cassis
- NewBase60 (and NewBase64) provides an open source implementation written completely in CASSIS v0.
- H2VX uses CASSIS v0.
- ASIN.cc uses CASSIS v0.1, directly including the same cassis.js file in script and PHP using the above documented technique.
- Whistle(4) is a personal URL shortener that uses CASSIS v0.1 to convert long descriptive URLs into short sharable/compressed URLs (using NewBase60) and back.
- Falcon is a personal publishing/syndicating/tweeting/updating web application that uses CASSIS v0.1.
Writing in CASSIS
Coding standards for compatibly writing in CASSIS.
- variable names must start with $. (for PHP compatibility)
- string concatenation must use strcat() function. (not '+' or '.' native operators)
- code outside of the cassis.js library MUST NOT use the js() test function.
- anything that depends on JS or PHP should be abstracted and placed into cassis.js.
- ...
Projects to be written
Troubleshooting
count is not a function
Problem: you get an error message like (e.g. on Safari / Develop / Show Error Console)
TypeError: Result of expression 'count' [1] is not a function.
Diagnosis: you're likely declaring a global variable in your code after you have script src="" included CASSIS, perhaps with a line like:
var count = 0;
Solution: remove the line of code assigning to count, recode your code to not depend on a global variable, or rename the variable to a global name that is unique to your site / path / application to avoid colliding with globals in others scripting libraries.
Details
Some of the details of how CASSIS works.
Detection
Due to the need to abstract some number of language differences in syntax and built-in functionality, a foundational library must be developed that can detect which language it is running in, and execute language specific code accordingly so that CASSIS v0 code itself will not require anything language specific.
The key to the CASSIS v0 foundational library is the detection and switching of code dependent on which programming language environment is currently running.
The following code(2) switches between javascript, PHP, C/C++ and Ruby if need be:
if ("00"==false) {/*javascript*/}
else if ("0"==false) {/*php*/}
else if (0==false) {/*c*/}
else {/*ruby*/}
For simplicity, it is sufficient to start with the ability to switch between javascript and one other language. From the possible candidates: PHP, Ruby, and C/C++, PHP is supported (nearly?) all web hosting environments and thus is the logical choice. We can simplify this test to check for JS or PHP environments as such:
function js() {
return ("00"==false);
}
This function is called by any foundational library function that needs to execute different code for javascript vs. PHP as follows:
if (js()) {
/* javascript */
}
else {
/* PHP */
}
V0.1 code
The latest CASSIS v0.1 code is hosted live at:
https://tantek.com/cassis.js
Improvements in V0.1 over V0
- integrated cassis.js. cassisv0php.js and cassis0.js have been fully integrated into cassis.js. This presents a much simpler inclusion model for both PHP and Javascript.
- alternating overlapping comments instead of PHP heredoc.
- many many more library functions.
V0 code
This section describes the initial functional version of CASSIS and is provided as historical documentation at this point (2010-031).
CASSIS v0 code is code that will run in PHP or javascript (and thus both on typical web servers, and typical web clients/browsers). Running CASSIS v0 code in javascript requires the use of an adapter library which re-implements some built-in PHP functions in javascript, documented in a latter section as cassisv0php.js.
CASSIS v0 code files must start with the following code sequence(3) to allow both PHP and javascript to execute properly:
<!-- <?php // -->
Similarly, CASSIS v0 code files must end with the following code sequence to properly balance and close out the PHP execution environment and the SGML/HTML comment opened at the start of the file in order to reduce/minimize any unintended effects of text outputted by PHP.
// ?> -->
common functions
One of best ways to avoid syntax differences between PHP and javascript is to use functions as much as possible. When PHP and javascript both have native (but differing in syntax) features for particular language functionality (e.g. string concatenation), the functionality must be abstracted in a common function.
The following block of CASSIS v0 code can be dropped into a CASSIS code file inline, or included as a separate cassis0.js file:
/* cassis0.js */
function js() {
return ("00"==false);
}
function strcat($s1,$s2) {
if (js()) { return $s1 + $s2; }
else { return $s1 . $s2; }
}
/* end cassis0.js */
javascript only functions
When one language has a native feature that is implemented via a function (perhaps built-in) in the other language, it is better to use that function than the native feature, and then implement a compatibility function for the language with the native feature.
E.g. string length is implemented in javascript with the native "length" property, e.g. alert("foo".length) displays 3. In PHP string length is implemented as the strlen() function. Thus we re-implement strlen() as a function in javascript using its native "length" property.
The following block of javascript code can be dropped into a CASSIS code file inline, or included as a separate cassis0php.js file:
/* cassis0php.js - processed only by javascript */
// ?>
<!-- <?php $js=<<<EJS
/* --> /**/
function strlen(s) {
return s.length;
}
function ord(s) {
return s.charCodeAt(0);
}
function substr(s,o,n) {
var m = strlen(s);
if (Math.abs(o)>=m) return false;
if (o<0) o=m+o;
if (n<0) n=m-o+n;
return s.substring(o,o+n);
}
function explode(d,s,n) {
return s.split(d,n);
}
function rawurlencode(s) {
return encodeURIComponent(s);
}
function htmlspecialchars(s) {
var c= [["&","&"],["<","<"],[">",">"],["'","'"],['"',"""]];
for (i=0;i<c.length;i++) {
s = s.replace(c[i][0],c[i][1]);
}
return s;
}
function str_ireplace(a,b,s) {
return s.replace(new RegExp(a,"gi"),b);
}
/* more javascript-only functions here */
/*
EJS;
/**/
/* end cassis0php.js */
A precise sequence of common HTML/SGML comments <!-- -->, block comments /*...*/, one line comments //, PHP execution environment entering <?php and exiting ?>, and the PHP "heredoc" <<< block string format is used to declare a function in javascript which is seen only as a string value block of text by PHP. The concept of using overlapping multi-lingual comments to pass different content to different language interpreters was first proposed and demonstrated in Semantic Scripting (posted 2002-11-21).
Using the above cassis0php.js code, CASSIS v0 code can call the "strlen" (to determine the length of a string) and "ord" functions, and such function calls will work in PHP or javascript.
PHP only functions
...to be written as needed.
History
- 2008-09-10 conceived. https://twitter.com/t/statuses/916632211 inspired by Bulletproof Ajax, undesirable DRY violation (duplicating code JS & PHP), and tired of rewriting in new languages. Picked JS as winner (most # of programmers, most # of companies spending most $ optimizing it). Goal determined: write application logic code once. Careful to not accidentally enable Skynet. Researched JS on the server, too hard to install/maintain, minimal/no web hosting services that provide it. But all web hosts run PHP. Asked the question of might there be an intersection of JS & PHP? Remembered that jQuery uses $ variable, thus JS allows $ in variable names, thus we can require that to create PHP compatible variable names when coding in JS.
- 2009-06-17 language detection. https://twitter.com/t/status/2215180366 falsy values research: comparing false to 0, "0", "00" treated differently by different languages.
- 2009-06-22 Javascript and PHP single file parsability. https://twitter.com/t/statuses/2287355907
- 2009 unknown date - tackled string concatenation difference '+' vs '.' (strcat 2 params, later unlimited)
- 2009 unknown date - figured out how to comment switch PHP-only and JS-only code blocks. introduced JS-only "strlen" and "ord" functions written in JS for JS, since PHP already has those as builtin functions.
- 2009 unknown date - figured out comment inverter and stateless closer (perhaps from my early CSS hacks).
- 2009-11-30 Epoch days sexagesimal (NewBase60) implementation for Whistle. https://twitter.com/t/statuses/6215480459
- 2010 unknown dates - various Falcon core functions and new features implemented in CASSIS.
- 2011-... CASSIS published on github: https://github.com/tantek/cassis
- 2011-05-20 gave CASSIS talk at FalsyValues.com
- 2011-07-16 gave CASSIS talk at Open Web Camp III
- ...
Related Background
Some of the building block ideas / idea-fragments that inspired or were incorporated into CASSIS:
- 2001: created box model hack, the first use of comments { voice-family:"\"}\""; } to trick different parsers into parsing different things.
- 2002: blogged Semantic Scripting which introduced:
- "principle of separation of script and markup"
- use of comments to trick HTML vs JS parsers to see different parts of the file, thus enable the ability to publish hypertext documentation inline in external JS files.
Reference
I have given the following talk on CASSIS and am available to give it at conferences, please contact me per CommunicationProtocols.
Title: CASSIS: Universal Client Server Javascript Now
Alternate Title: cassis.js: Code That Runs in both JS & PHP - Natively
Excerpt:
This talk is about how I use language hacks to run the same code natively on PHP and Javascript (JS), which I call CASSIS for Client And Server Scripting Implementation Subset.
I'll describe how I discovered CASSIS, how to use the open source library cassis.js to write middleware logic once for both client & server, and real-world use cases including where I've successfully deployed cassis.js for years (even as an essential part of my own site tantek.com).
Description:
This talk is about how I use language hacks* to run the same code natively on PHP and Javascript (JS), which I call CASSIS for Client And Server Scripting Implementation Subset.
Like any modern web developer, I want my site to work whether or not Javascript (JS) is supported, e.g. search engines which don’t execute it, on older browsers where users have disabled it, or perhaps most frequently, on mobile browsers with slow and unreliable network access that simply fails to load it. Tired of writing my code twice (once for JS, once for PHP), I started tinkering to see if there was a way to write code that would run in either simultaneously (without translation).
In this talk l’ll describe how I discovered CASSIS, how to use the open source library cassis.js to write middleware logic (math, datetime computations, string processing, parsing) once for both client & server, and real-world use cases including where I’ve successfully deployed cassis.js for years (even as an essential part of my own site tantek.com).
*You might be familiar with a previous language hack of mine: Box Model Hack.
Tags:
php, javascript, language, js, client, server
Return to MyNextStartup \ ProjectsList \ FrontPage.
Comments (0)
You don't have permission to comment on this page.