Compare commits
7 Commits
fix/renami
...
feat/asc-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78c241f68a | ||
|
|
775ae3de9b | ||
|
|
6fa68b9d6b | ||
|
|
b7c48c81a4 | ||
|
|
33019835ea | ||
|
|
fbc9a038ef | ||
|
|
318633c5e1 |
@@ -7,6 +7,7 @@ import { useRouter } from 'next/router'
|
||||
|
||||
import Box from './Box'
|
||||
import Container from './Container'
|
||||
import asc from 'assemblyscript/dist/asc'
|
||||
import { createNewFile, saveFile } from '../state/actions'
|
||||
import { apiHeaderFiles } from '../state/constants'
|
||||
import state from '../state'
|
||||
@@ -200,15 +201,25 @@ const HooksEditor = () => {
|
||||
defaultValue={file?.content}
|
||||
// onChange={val => (state.files[snap.active].content = val)} // Auto save?
|
||||
beforeMount={monaco => {
|
||||
// if (!snap.editorCtx) {
|
||||
// snap.files.forEach(file =>
|
||||
// monaco.editor.createModel(
|
||||
// file.content,
|
||||
// file.language,
|
||||
// monaco.Uri.parse(`file:///work/c/${file.name}`)
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
if (!snap.editorCtx) {
|
||||
snap.files.forEach(file =>
|
||||
monaco.editor.createModel(
|
||||
file.content,
|
||||
file.language,
|
||||
monaco.Uri.parse(`file:///work/c/${file.name}`)
|
||||
)
|
||||
)
|
||||
}
|
||||
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
|
||||
experimentalDecorators: true
|
||||
})
|
||||
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
||||
diagnosticCodesToIgnore: [1206]
|
||||
})
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||
asc.definitionFiles.assembly,
|
||||
'assemblyscript/std/assembly/index.d.ts'
|
||||
)
|
||||
|
||||
// create the web socket
|
||||
if (!subscriptionRef.current) {
|
||||
@@ -218,11 +229,7 @@ const HooksEditor = () => {
|
||||
aliases: ['C', 'c', 'H', 'h'],
|
||||
mimetypes: ['text/plain']
|
||||
})
|
||||
monaco.languages.register({
|
||||
id: 'text',
|
||||
extensions: ['.txt'],
|
||||
mimetypes: ['text/plain'],
|
||||
})
|
||||
|
||||
MonacoServices.install(monaco)
|
||||
const webSocket = createWebSocket(
|
||||
process.env.NEXT_PUBLIC_LANGUAGE_SERVER_API_ENDPOINT || ''
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from './Dialog'
|
||||
import { Plus, X } from 'phosphor-react'
|
||||
import { styled } from '../stitches.config'
|
||||
import { capitalize, getFileExtention } from '../utils/helpers'
|
||||
import { capitalize } from '../utils/helpers'
|
||||
import ContextMenu, { ContentMenuOption } from './ContextMenu'
|
||||
|
||||
const ErrorText = styled(Text, {
|
||||
@@ -97,7 +97,7 @@ export const Tabs = ({
|
||||
if (!tabname) {
|
||||
return { error: `Please enter ${label.toLocaleLowerCase()} name.` }
|
||||
}
|
||||
let ext = getFileExtention(tabname)
|
||||
let ext = (tabname.includes('.') && tabname.split('.').pop()) || ''
|
||||
|
||||
if (!ext && defaultExtension) {
|
||||
ext = defaultExtension
|
||||
@@ -109,7 +109,7 @@ export const Tabs = ({
|
||||
if (extensionRequired && !ext) {
|
||||
return { error: 'File extension is required!' }
|
||||
}
|
||||
if (allowedExtensions && ext && !allowedExtensions.includes(ext)) {
|
||||
if (allowedExtensions && !allowedExtensions.includes(ext)) {
|
||||
return { error: 'This file extension is not allowed!' }
|
||||
}
|
||||
if (headerExtraValidation && !tabname.match(headerExtraValidation.regex)) {
|
||||
|
||||
@@ -8,8 +8,16 @@ module.exports = {
|
||||
config.resolve.alias['vscode'] = require.resolve(
|
||||
'@codingame/monaco-languageclient/lib/vscode-compatibility'
|
||||
)
|
||||
config.experiments = {
|
||||
topLevelAwait: true,
|
||||
layers: true
|
||||
}
|
||||
if (!isServer) {
|
||||
config.resolve.fallback.fs = false
|
||||
config.resolve.fallback = {
|
||||
...config.resolve.fallback,
|
||||
fs: false,
|
||||
module: false
|
||||
}
|
||||
}
|
||||
config.module.rules.push({
|
||||
test: /\.md$/,
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"@radix-ui/react-switch": "^0.1.5",
|
||||
"@radix-ui/react-tooltip": "^0.1.7",
|
||||
"@stitches/react": "^1.2.8",
|
||||
"assemblyscript": "^0.20.19",
|
||||
"base64-js": "^1.5.1",
|
||||
"comment-parser": "^1.3.1",
|
||||
"dinero.js": "^1.9.1",
|
||||
|
||||
@@ -10,11 +10,10 @@ import Box from '../../components/Box'
|
||||
import Button from '../../components/Button'
|
||||
import Popover from '../../components/Popover'
|
||||
import RunScript from '../../components/RunScript'
|
||||
import state, { IFile } from '../../state'
|
||||
import state from '../../state'
|
||||
import { compileCode } from '../../state/actions'
|
||||
import { getSplit, saveSplit } from '../../state/actions/persistSplits'
|
||||
import { styled } from '../../stitches.config'
|
||||
import { getFileExtention } from '../../utils/helpers'
|
||||
|
||||
const HooksEditor = dynamic(() => import('../../components/HooksEditor'), {
|
||||
ssr: false
|
||||
@@ -148,8 +147,6 @@ const CompilerSettings = () => {
|
||||
const Home: NextPage = () => {
|
||||
const snap = useSnapshot(state)
|
||||
|
||||
const activeFile = snap.files[snap.active] as IFile | undefined
|
||||
const activeFileExt = getFileExtention(activeFile?.name)
|
||||
return (
|
||||
<Split
|
||||
direction="vertical"
|
||||
@@ -162,7 +159,8 @@ const Home: NextPage = () => {
|
||||
>
|
||||
<main style={{ display: 'flex', flex: 1, position: 'relative' }}>
|
||||
<HooksEditor />
|
||||
{activeFileExt === 'c' && (
|
||||
{(snap.files[snap.active]?.name?.split('.')?.[1]?.toLowerCase() === 'c' ||
|
||||
snap.files[snap.active]?.name?.split('.')?.[1]?.toLowerCase() === 'ts') && (
|
||||
<Hotkeys
|
||||
keyName="command+b,ctrl+b"
|
||||
onKeyDown={() => !snap.compiling && snap.files.length && compileCode(snap.active)}
|
||||
@@ -188,15 +186,17 @@ const Home: NextPage = () => {
|
||||
<Play weight="bold" size="16px" />
|
||||
Compile to Wasm
|
||||
</Button>
|
||||
<Popover content={<CompilerSettings />}>
|
||||
<Button variant="primary" css={{ px: '10px' }}>
|
||||
<Gear size="16px" />
|
||||
</Button>
|
||||
</Popover>
|
||||
{snap.files[snap.active].language === 'c' && (
|
||||
<Popover content={<CompilerSettings />}>
|
||||
<Button variant="primary" css={{ px: '10px' }}>
|
||||
<Gear size="16px" />
|
||||
</Button>
|
||||
</Popover>
|
||||
)}
|
||||
</Flex>
|
||||
</Hotkeys>
|
||||
)}
|
||||
{activeFileExt === 'js' && (
|
||||
{snap.files[snap.active]?.name?.split('.')?.[1]?.toLowerCase() === 'js' && (
|
||||
<Hotkeys
|
||||
keyName="command+b,ctrl+b"
|
||||
onKeyDown={() => !snap.compiling && snap.files.length && compileCode(snap.active)}
|
||||
@@ -212,7 +212,7 @@ const Home: NextPage = () => {
|
||||
gap: '$2'
|
||||
}}
|
||||
>
|
||||
<RunScript file={activeFile as IFile} />
|
||||
<RunScript file={snap.files[snap.active]} />
|
||||
</Flex>
|
||||
</Hotkeys>
|
||||
)}
|
||||
@@ -228,7 +228,7 @@ const Home: NextPage = () => {
|
||||
>
|
||||
<LogBox title="Development Log" clearLog={() => (state.logs = [])} logs={snap.logs} />
|
||||
</Flex>
|
||||
{activeFileExt === 'js' && (
|
||||
{snap.files[snap.active]?.name?.split('.')?.[1]?.toLowerCase() === 'js' && (
|
||||
<Flex
|
||||
css={{
|
||||
flex: 1
|
||||
|
||||
BIN
public/cleaner.wasm
Executable file
BIN
public/cleaner.wasm
Executable file
Binary file not shown.
@@ -6,6 +6,8 @@ import { saveFile } from './saveFile'
|
||||
import { decodeBinary } from '../../utils/decodeBinary'
|
||||
import { ref } from 'valtio'
|
||||
|
||||
import Cleaner from '../../utils/cleaner/cleaner'
|
||||
|
||||
/* compileCode sends the code of the active file to compile endpoint
|
||||
* If all goes well you will get base64 encoded wasm file back with
|
||||
* some extra logging information if we can provide it. This function
|
||||
@@ -13,18 +15,138 @@ import { ref } from 'valtio'
|
||||
* out of it and store both in global state.
|
||||
*/
|
||||
export const compileCode = async (activeId: number) => {
|
||||
let asc: typeof import('assemblyscript/dist/asc') | undefined
|
||||
// Save the file to global state
|
||||
saveFile(false, activeId)
|
||||
if (!process.env.NEXT_PUBLIC_COMPILE_API_ENDPOINT) {
|
||||
throw Error('Missing env!')
|
||||
}
|
||||
// Bail out if we're already compiling
|
||||
// Bail out if we're already compiling
|
||||
if (state.compiling) {
|
||||
// if compiling is ongoing return // TODO Inform user about it.
|
||||
return
|
||||
}
|
||||
// Set loading state to true
|
||||
state.compiling = true
|
||||
if (typeof window !== 'undefined') {
|
||||
// IF AssemblyScript
|
||||
if (
|
||||
state.files[activeId].language.toLowerCase() === 'ts' ||
|
||||
state.files[activeId].language.toLowerCase() === 'typescript'
|
||||
) {
|
||||
if (!asc) {
|
||||
asc = await import('assemblyscript/dist/asc')
|
||||
}
|
||||
const files: { [key: string]: string } = {}
|
||||
state.files.forEach(file => {
|
||||
files[file.name] = file.content
|
||||
})
|
||||
const res = await asc.main(
|
||||
[
|
||||
state.files[activeId].name,
|
||||
'--textFile',
|
||||
'-o',
|
||||
`${state.files[activeId].name}.wasm`,
|
||||
'--runtime',
|
||||
'stub',
|
||||
'-O3',
|
||||
'--disable',
|
||||
'bulk-memory'
|
||||
],
|
||||
{
|
||||
readFile: (name, baseDir) => {
|
||||
const currentFile = state.files.find(file => file.name === name)
|
||||
if (currentFile) {
|
||||
return currentFile.content
|
||||
}
|
||||
return null
|
||||
},
|
||||
writeFile: async (name, data, baseDir) => {
|
||||
const curr = state.files.find(file => file.name === name.replace('.wasm', ''))
|
||||
if (curr) {
|
||||
const cleaner = await Cleaner({
|
||||
locateFile: (file: string) => {
|
||||
return `/${file}`
|
||||
}
|
||||
})
|
||||
|
||||
cleaner.FS.mkdir('compiled')
|
||||
cleaner.FS.createDataFile('/compiled', `${curr?.name}.wasm`, data, true, true)
|
||||
await cleaner.callMain([`/compiled/${curr?.name}.wasm`])
|
||||
const newFileUArr = cleaner.FS.readFile(`/compiled/${curr?.name}.wasm`) as Uint8Array
|
||||
// lets remove the file from the file system
|
||||
cleaner.FS.unlink(`/compiled/${curr.name}.wasm`)
|
||||
// lets remove the directory
|
||||
cleaner.FS.rmdir('compiled')
|
||||
|
||||
curr.compiledContent = ref(newFileUArr)
|
||||
}
|
||||
|
||||
const ww = (await import('wabt')).default()
|
||||
if (curr?.compiledContent) {
|
||||
if (curr.compiledContent instanceof Uint8Array) {
|
||||
const myModule = ww.readWasm(curr.compiledContent, {
|
||||
readDebugNames: true
|
||||
})
|
||||
myModule.applyNames()
|
||||
const compiledWat = myModule.toText({ foldExprs: false, inlineExport: false })
|
||||
curr.compiledWatContent = compiledWat
|
||||
}
|
||||
}
|
||||
toast.success('Compiled successfully!', { position: 'bottom-center' })
|
||||
},
|
||||
listFiles: (dirname, baseDir) => {
|
||||
console.log('listFiles: ' + dirname + ', baseDir=' + baseDir)
|
||||
return []
|
||||
}
|
||||
}
|
||||
)
|
||||
// In case you want to compile just single file
|
||||
// const res = await asc.compileString(state.files[activeId].content, {
|
||||
// optimizeLevel: 3,
|
||||
// runtime: 'stub',
|
||||
// })
|
||||
|
||||
if (res.error?.message) {
|
||||
state.compiling = false
|
||||
state.logs.push({
|
||||
type: 'error',
|
||||
message: res.error.message
|
||||
})
|
||||
state.logs.push({
|
||||
type: 'error',
|
||||
message: res.stderr.toString()
|
||||
})
|
||||
return
|
||||
}
|
||||
if (res.stdout) {
|
||||
state.files[activeId].lastCompiled = new Date()
|
||||
console.log(res.stdout.toString())
|
||||
state.files[activeId].compiledValueSnapshot = state.files[activeId].content
|
||||
state.logs.push({
|
||||
type: 'success',
|
||||
message: `File ${state.files?.[activeId]?.name} compiled successfully. Ready to deploy.`,
|
||||
link: Router.asPath.replace('develop', 'deploy'),
|
||||
linkText: 'Go to deploy'
|
||||
})
|
||||
}
|
||||
// if (res.stdout) {
|
||||
// const wat = res.stdout.toString()
|
||||
// state.files[activeId].lastCompiled = new Date()
|
||||
// state.files[activeId].compiledWatContent = wat
|
||||
// state.files[activeId].compiledValueSnapshot = state.files[activeId].content
|
||||
// state.logs.push({
|
||||
// type: 'success',
|
||||
// message: `File ${state.files?.[activeId]?.name} compiled successfully. Ready to deploy.`,
|
||||
// link: Router.asPath.replace('develop', 'deploy'),
|
||||
// linkText: 'Go to deploy'
|
||||
// })
|
||||
// }
|
||||
console.log('nääää')
|
||||
state.compiling = false
|
||||
return
|
||||
}
|
||||
}
|
||||
state.logs = []
|
||||
const file = state.files[activeId]
|
||||
try {
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { getFileExtention } from '../../utils/helpers'
|
||||
import state, { IFile } from '../index'
|
||||
|
||||
const languageMapping: Record<string, string | undefined> = {
|
||||
const languageMapping = {
|
||||
ts: 'typescript',
|
||||
js: 'javascript',
|
||||
md: 'markdown',
|
||||
c: 'c',
|
||||
h: 'c',
|
||||
txt: 'text'
|
||||
}
|
||||
|
||||
other: ''
|
||||
} /* Initializes empty file to global state */
|
||||
export const createNewFile = (name: string) => {
|
||||
const ext = getFileExtention(name) || ''
|
||||
|
||||
const emptyFile: IFile = { name, language: languageMapping[ext] || 'text', content: '' }
|
||||
const tempName = name.split('.')
|
||||
const fileExt = tempName[tempName.length - 1] || 'other'
|
||||
const emptyFile: IFile = {
|
||||
name,
|
||||
language: languageMapping[fileExt as 'ts' | 'js' | 'md' | 'c' | 'h' | 'other'],
|
||||
content: ''
|
||||
}
|
||||
state.files.push(emptyFile)
|
||||
state.active = state.files.length - 1
|
||||
}
|
||||
@@ -22,8 +24,5 @@ export const renameFile = (oldName: string, nwName: string) => {
|
||||
const file = state.files.find(file => file.name === oldName)
|
||||
if (!file) throw Error(`No file exists with name ${oldName}`)
|
||||
|
||||
const ext = getFileExtention(nwName) || ''
|
||||
const language = languageMapping[ext] || 'text'
|
||||
file.name = nwName
|
||||
file.language = language
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ function toHex(str: string) {
|
||||
return result.toUpperCase()
|
||||
}
|
||||
|
||||
function arrayBufferToHex(arrayBuffer?: ArrayBuffer | null) {
|
||||
function arrayBufferToHex(arrayBuffer?: ArrayBuffer | Uint8Array | null) {
|
||||
if (!arrayBuffer) {
|
||||
return ''
|
||||
}
|
||||
@@ -36,7 +36,7 @@ function arrayBufferToHex(arrayBuffer?: ArrayBuffer | null) {
|
||||
throw new TypeError('Expected input to be an ArrayBuffer')
|
||||
}
|
||||
|
||||
var view = new Uint8Array(arrayBuffer)
|
||||
var view = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer)
|
||||
var result = ''
|
||||
var value
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export interface IFile {
|
||||
language: string
|
||||
content: string
|
||||
compiledValueSnapshot?: string
|
||||
compiledContent?: ArrayBuffer | null
|
||||
compiledContent?: ArrayBuffer | Uint8Array | null
|
||||
compiledWatContent?: string | null
|
||||
lastCompiled?: Date
|
||||
containsErrors?: boolean
|
||||
|
||||
4995
utils/cleaner/cleaner.js
Normal file
4995
utils/cleaner/cleaner.js
Normal file
File diff suppressed because it is too large
Load Diff
BIN
utils/cleaner/cleaner.wasm
Executable file
BIN
utils/cleaner/cleaner.wasm
Executable file
Binary file not shown.
@@ -13,9 +13,3 @@ export const capitalize = (value?: string) => {
|
||||
|
||||
return value[0].toLocaleUpperCase() + value.slice(1)
|
||||
}
|
||||
|
||||
export const getFileExtention = (filename?: string): string | undefined => {
|
||||
if (!filename) return
|
||||
const ext = (filename.includes('.') && filename.split('.').pop()) || undefined
|
||||
return ext
|
||||
}
|
||||
|
||||
18
yarn.lock
18
yarn.lock
@@ -1289,6 +1289,14 @@ array.prototype.flatmap@^1.2.5:
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.19.0"
|
||||
|
||||
assemblyscript@^0.20.19:
|
||||
version "0.20.19"
|
||||
resolved "https://registry.yarnpkg.com/assemblyscript/-/assemblyscript-0.20.19.tgz#7c29f506a31d526f7d7e3b22908cc8774b378681"
|
||||
integrity sha512-IJN2CaAwCdRgTSZz3GiuYyXtXIjETBrlzky9ww9jFlEgH8i0pNFt6MAS3viogkofem+rcY6Fhr/clk+b6LWLBw==
|
||||
dependencies:
|
||||
binaryen "109.0.0-nightly.20220813"
|
||||
long "^5.2.0"
|
||||
|
||||
assert@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz"
|
||||
@@ -1392,6 +1400,11 @@ bignumber.js@^9.0.0:
|
||||
resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz"
|
||||
integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==
|
||||
|
||||
binaryen@109.0.0-nightly.20220813:
|
||||
version "109.0.0-nightly.20220813"
|
||||
resolved "https://registry.yarnpkg.com/binaryen/-/binaryen-109.0.0-nightly.20220813.tgz#6928acf8820fc1270d41dbb157c0c2337a067d20"
|
||||
integrity sha512-u85Ti3LiGRrV0HqdNDRknalkx7QiCSL0jNsEsT522nnZacWxUaSJEILphxc2OnzmHVtdiWBE3c4lEzlU3ZEyDw==
|
||||
|
||||
bindings@^1.3.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz"
|
||||
@@ -2960,6 +2973,11 @@ lodash@^4.17.15, lodash@^4.17.4:
|
||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
long@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-5.2.0.tgz#2696dadf4b4da2ce3f6f6b89186085d94d52fd61"
|
||||
integrity sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
|
||||
|
||||
Reference in New Issue
Block a user