Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Website hacks #317

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 0 additions & 11 deletions stopify-compiler-cloud-function/test.js

This file was deleted.

111 changes: 105 additions & 6 deletions stopify-compiler-cloud-function/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ genericCompiler('pyjs', `${thirdPartyCompilers}/pyjs`, {
es: 'sane',
hofs: 'builtin',
jsArgs: 'faithful',
requireRuntime: false
requireRuntime: false,
eval: false
});

genericCompiler('emscripten', `${thirdPartyCompilers}/emscripten`, {
Expand All @@ -115,7 +116,8 @@ genericCompiler('emscripten', `${thirdPartyCompilers}/emscripten`, {
es: 'sane',
hofs: 'builtin',
jsArgs: 'simple',
requireRuntime: false
requireRuntime: false,
eval: false
});

genericCompiler('bucklescript', `${thirdPartyCompilers}/bucklescript`, {
Expand All @@ -126,7 +128,8 @@ genericCompiler('bucklescript', `${thirdPartyCompilers}/bucklescript`, {
es: 'sane',
hofs: 'builtin',
jsArgs: 'simple',
requireRuntime: false
requireRuntime: false,
eval: false
});

genericCompiler('scalajs', `${thirdPartyCompilers}/scalajs`, {
Expand All @@ -137,7 +140,8 @@ genericCompiler('scalajs', `${thirdPartyCompilers}/scalajs`, {
es: 'sane',
hofs: 'builtin',
jsArgs: 'simple',
requireRuntime: false
requireRuntime: false,
eval: false
});

genericCompiler('clojurescript', `${thirdPartyCompilers}/clojurescript`, {
Expand All @@ -148,7 +152,8 @@ genericCompiler('clojurescript', `${thirdPartyCompilers}/clojurescript`, {
es: 'sane',
hofs: 'builtin',
jsArgs: 'simple',
requireRuntime: false
requireRuntime: false,
eval: false
});

genericCompiler('dart2js', `${thirdPartyCompilers}/dart2js`, {
Expand All @@ -159,5 +164,99 @@ genericCompiler('dart2js', `${thirdPartyCompilers}/dart2js`, {
es: 'sane',
hofs: 'builtin',
jsArgs: 'simple',
requireRuntime: false
requireRuntime: false,
eval: false
});

stopify.post('/pyjs-fast', bodyParser.text({ type: '*/*' }), async (req, resp) => {
try {
resp.set('Access-Control-Allow-Origin', '*');
resp.set('Access-Control-Allow-Methods', 'POST');

const { filename, exists } = await checkCache('pyjs-fast', req.body);
if (exists) {
return resp.send(filename);
}
console.info(`Compiling PyJS (fast) program (${req.body.length} bytes)`);
const url = `${thirdPartyCompilers}/pyjs-fast`;
const jsCode = await request.post(url, { headers, body: req.body });
console.info(`Stopifying program (${jsCode.length} bytes)`);
const dir = await tmpDir();
try {
const jsPath = `${dir}/original.js`;
await fs.writeFile(jsPath, jsCode + '\npygwtOnLoad();');
const stopifiedJsCode = await stopifyCompiler.stopify(jsPath, {
compileFunction: 'module',
getters: false,
debug: false,
captureMethod: 'lazy',
newMethod: 'wrapper',
es: 'sane',
hofs: 'builtin',
jsArgs: 'faithful',
requireRuntime: false,
eval: false
});
const prelude = await fs.readFile(__dirname + '/../pyjs_prelude.lazy.wrapper.faithful.js');
await bucket.file(filename).save(prelude + stopifiedJsCode + `
$__R.delimit(function () {
$S.onEnd();
});`
);
return resp.send(filename);
}
finally {
await fs.remove(dir);
}
}
catch (exn) {
resp.statusCode = 503;
const reason =
(exn.name === 'StatusCodeError' ? exn.response.body : exn).toString();
console.error(`Error: ${reason}`);
return resp.send(reason.toString());
}
});

stopify.post('/js', bodyParser.text({ type: '*/*' }), async (req, resp) => {
try {
resp.set('Access-Control-Allow-Origin', '*');
resp.set('Access-Control-Allow-Methods', 'POST');

const { filename, exists } = await checkCache('js', req.body);
if (exists) {
return resp.send(filename);
}
console.info(`Compiling JavaScript program (${req.body.length} bytes)`);
const jsCode = req.body;
const dir = await tmpDir();
try {
const jsPath = `${dir}/original.js`;
await fs.writeFile(jsPath, jsCode);
const stopifiedJsCode = await stopifyCompiler.stopify(jsPath, {
compileFunction: false,
getters: false,
debug: true,
captureMethod: 'lazy',
newMethod: 'wrapper',
es: 'sane',
hofs: 'builtin',
jsArgs: 'faithful',
requireRuntime: false,
eval: false
});
await bucket.file(filename).save(stopifiedJsCode);
return resp.send(filename);
}
finally {
await fs.remove(dir);
}
}
catch (exn) {
resp.statusCode = 503;
const reason =
(exn.name === 'StatusCodeError' ? exn.response.body : exn).toString();
console.error(`Error: ${reason}`);
return resp.send(reason.toString());
}
});
2 changes: 1 addition & 1 deletion stopify-compiler-cloud-function/ts/testServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import * as index from './index';

const app = express();
app.use(index.stopifyTesting);
app.listen(8080, '0.0.0.0');
app.listen(8081, '0.0.0.0');

2 changes: 1 addition & 1 deletion stopify-continuations/src/callcc/boxAssignables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ const visitor = {
// topFunction. It shouldn't be boxed since we want to preserve its
// signature.
if (vars.includes(path.node.id.name) &&
!(state.opts.compileFunction && (<any>path.node).topFunction)) {
!(state.opts.compileFunction === true && (<any>path.node).topFunction)) {
const fun = t.functionExpression(
fastFreshId.fresh('fun'),
path.node.params,
Expand Down
2 changes: 1 addition & 1 deletion stopify-continuations/src/callcc/callcc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const visitor: Visitor = {
path.stop();

let toShift;
if (opts.compileFunction) {
if (opts.compileFunction === true) {
if (t.isFunctionDeclaration(path.node.body[0])) {
toShift = (<t.FunctionDeclaration>path.node.body[0]).body.body
}
Expand Down
2 changes: 1 addition & 1 deletion stopify-continuations/src/callcc/delimitTopLevel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const visitor = {
// leave intact
}
else {
if (state.opts.compileFunction && (<any>body[i]).topFunction) {
if (state.opts.compileFunction !== false && (<any>body[i]).topFunction) {
}
else {
body[i] = delimitStmt(body[i]);
Expand Down
3 changes: 2 additions & 1 deletion stopify-continuations/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export type CaptureMethod = 'eager' | 'retval' | 'lazy' | 'original' | 'fudge';
export type HandleNew = 'direct' | 'wrapper'
export type CompileFunction = boolean | 'module';

export interface CompilerOpts {
compileFunction?: boolean,
compileFunction?: CompileFunction,
getters: boolean,
debug: boolean,
captureMethod: CaptureMethod,
Expand Down
59 changes: 49 additions & 10 deletions stopify-static-website/ts/languages.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as stopifyCompiler from 'stopify';

export interface Language {
compileUrl: string,
defaultCode: string
Expand All @@ -7,6 +9,31 @@ export interface Language {

const compilerBase = 'https://us-central1-arjun-umass.cloudfunctions.net/stopify';

export function runtimeOpts(name: string): stopifyCompiler.Opts {
if (name === 'pyjs' || name === 'js') {
return {
filename: '',
estimator: 'reservoir',
yieldInterval: 100,
timePerElapsed: 1,
resampleInterval: 1,
variance: false,
env: 'chrome',
stop: undefined
};
}

return {
filename: '',
estimator: 'countdown',
yieldInterval: 1,
timePerElapsed: 1,
resampleInterval: 1,
variance: false,
env: 'chrome',
stop: undefined
};
}

export const langs: { [name: string]: Language } = {
'Dart': {
Expand Down Expand Up @@ -86,16 +113,28 @@ object Runner extends JSApp {
stepSupported: false,
aceMode: 'python',
defaultCode:
`def run_forever():
i = 0
while(True):
if i > 10000:
i = 0
i += 1
print i
`def fib(n):
print "fib(" + str(n) + ")"
if n == 0 or n == 1:
return 1
return fib(n-1) + fib(n-2)

run_forever()
`,
compileUrl: `${compilerBase}/pyjs`
print (fib(15))`,
compileUrl: `${compilerBase}/pyjs-fast`
},
JavaScript: {
stepSupported: true,
aceMode: 'js',
defaultCode:
`function fib(n) {
console.log('fib(' + n + ')');
if (n === 0 || n === 1) {
return 1;
}
return fib(n-1) + fib(n-2);
}

fib(15);`,
compileUrl: `${compilerBase}/js`
},
};
18 changes: 5 additions & 13 deletions stopify-static-website/ts/stopify.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import AceEditor from 'react-ace';
import { StopifyAce } from './StopifyAce';
import * as browser from 'detect-browser'
import * as ace from 'brace';
import { langs } from './languages';
import { langs, runtimeOpts } from './languages';

import * as stopifyCompiler from 'stopify';

Expand Down Expand Up @@ -40,6 +40,7 @@ class MultilingualStopifyEditor extends React.Component<{}, {language: string}>
<ul className="dropdown-menu">
<li><a href="#" onClick={() => this.setState({ language: 'Dart' })}>Dart</a></li>
<li><a href="#" onClick={() => this.setState({ language: 'Python' })}>Python</a></li>
<li><a href="#" onClick={() => this.setState({ language: 'JavaScript' })}>JavaScript</a></li>
<li><a href="#" onClick={() => this.setState({ language: 'Scala' })}>Scala</a></li>
<li><a href="#" onClick={() => this.setState({ language: 'OCaml' })}>OCaml</a></li>
<li><a href="#" onClick={() => this.setState({ language: 'C++' })}>C++</a></li>
Expand Down Expand Up @@ -141,16 +142,7 @@ class StopifyEditor extends React.Component<{ language: string }, StopifyEditorS
}
}))
.then(path => {
const opts: stopifyCompiler.Opts = {
filename: path,
estimator: 'countdown',
yieldInterval: 1,
timePerElapsed: 1,
resampleInterval: 1,
variance: false,
env: browser.name as any,
stop: undefined
};
const opts = runtimeOpts(this.state.language);
this.setState({
rhs: { type: 'iframe', url: './container.html', opts: opts, path: path }
});
Expand Down Expand Up @@ -249,8 +241,8 @@ class StopifyEditor extends React.Component<{ language: string }, StopifyEditorS
else {
// The "key" in the iframe is unique and forces a full reload.
rhs = <iframe key={this.state.rhs.url} ref={(frame) => this.iframe = frame}
src={this.state.rhs.url} width='100%' height='100%'
style={{border: 'none', overflow: 'hidden'}}>
src={this.state.rhs.url} width='100%'
style={{border: 'none', overflow: 'hidden', height: '80vh' }}>
</iframe>;
}
return <div className="row display-flex">
Expand Down
22 changes: 22 additions & 0 deletions stopify-third-party-compiler-container/server/ts/pyjsFast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import * as request from 'request-promise-native';
import { tmpDir, exec } from './misc';

/**
* Compiles a Python module using PyJS, but does not link it to the PyJS
* runtime system. The produced module is called 'main' and the PyJS runtime
* must be written to load 'main'.
*
* @param code body of the python module
*/
export async function compile(code: string): Promise<string> {
const dir = await tmpDir();
try {
await fs.writeFile(`${dir}/main.py`, code);
return await exec(`pyjscompile main.py`, dir);
}
finally {
await fs.remove(dir);
}
}
2 changes: 2 additions & 0 deletions stopify-third-party-compiler-container/server/ts/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as bucklescript from './bucklescript';
import * as clojurescript from './clojurescript';
import * as scalajs from './scalajs';
import * as dart2js from './dart2js';
import * as pyjsFast from './pyjsFast';

export const app = express();
app.use(morgan('short'));
Expand All @@ -31,5 +32,6 @@ compiler('/bucklescript', bucklescript.compile);
compiler('/clojurescript', clojurescript.compile);
compiler('/scalajs', scalajs.compile);
compiler('/dart2js', dart2js.compile);
compiler('/pyjs-fast', pyjsFast.compile);

app.listen(8080);