-
Notifications
You must be signed in to change notification settings - Fork 133
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
Basic Arrow function support + array methods #123
Changes from all commits
967d540
4f0b52a
6c1a81f
7808f67
0e5b7d6
d3e6bdb
e864f77
220b031
1a17a8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
export default function (jsep) { | ||
if (typeof jsep === 'undefined') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure this is a good pattern, for the following reasons:
Ideally, third-party code should not need to run any code to activate plugins, including them should just work. One way to do that is if each plugin simply imports jsep using classic ESM imports. import jsep from "jsep.js";
import "jsep-plugins/jsep-arrow-function.js"; The main downside of this is that since plugins import jsep, they need to know its path (relative or not). |
||
return; | ||
} | ||
|
||
const EQUAL_CODE = 61; // = | ||
const GTHAN_CODE = 62; // > | ||
const ARROW_EXP = 'ArrowFunctionExpression'; | ||
jsep.addBinaryOp('=>', 0); | ||
|
||
jsep.hooks.add('gobble-expression', function gobbleArrowExpression(env) { | ||
if (env.exprICode(env.index) === EQUAL_CODE) { | ||
// arrow expression: () => expr | ||
env.index++; | ||
if (env.exprICode(env.index) === GTHAN_CODE) { | ||
env.index++; | ||
env.node = { | ||
type: ARROW_EXP, | ||
params: env.node ? [env.node] : null, | ||
body: env.gobbleExpression(), | ||
}; | ||
} | ||
else { | ||
env.throwError('Expected >'); | ||
} | ||
} | ||
}); | ||
|
||
// This is necessary when adding '=' as a binary operator (for assignment) | ||
// Otherwise '>' throws an error for the right-hand side | ||
jsep.hooks.add('after-expression', function fixBinaryArrow(env) { | ||
if (env.node && env.node.operator === '=>') { | ||
env.node = { | ||
type: 'ArrowFunctionExpression', | ||
params: env.node.left ? [env.node.left] : null, | ||
body: env.node.right, | ||
}; | ||
} | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
export default function (jsep) { | ||
if (typeof jsep === 'undefined') { | ||
return; | ||
} | ||
|
||
const assignmentOperators = new Set([ | ||
'=', | ||
'*=', | ||
'**=', | ||
'/=', | ||
'%=', | ||
'+=', | ||
'-=', | ||
'<<=', | ||
'>>=', | ||
'>>>=', | ||
'&=', | ||
'^=', | ||
'|=', | ||
]); | ||
assignmentOperators.forEach(op => jsep.addBinaryOp(op, 0.9)); | ||
|
||
jsep.hooks.add('after-expression', function gobbleAssignment(env) { | ||
if (assignmentOperators.has(env.node.operator)) { | ||
env.node.type = 'AssignmentExpression'; | ||
} | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
export default function (jsep) { | ||
if (typeof jsep === 'undefined') { | ||
return; | ||
} | ||
|
||
const FSLSH_CODE = 47; // / | ||
const ASTSK_CODE = 42; // * | ||
const LF_CODE = 10; | ||
|
||
jsep.hooks.add('gobble-spaces', function gobbleComment(env) { | ||
if (env.exprICode(env.index) === FSLSH_CODE) { | ||
let ch = env.exprICode(env.index + 1); | ||
if (ch === FSLSH_CODE) { | ||
// read to end of line | ||
env.index += 2; | ||
while (ch !== LF_CODE && !isNaN(ch)) { | ||
ch = env.exprICode(++env.index); | ||
} | ||
} | ||
else if (ch === ASTSK_CODE) { | ||
// read to */ or end of input | ||
env.index += 2; | ||
while (!isNaN(ch)) { | ||
ch = env.exprICode(++env.index); | ||
if (ch === ASTSK_CODE) { | ||
ch = env.exprICode(++env.index); | ||
if (ch === FSLSH_CODE) { | ||
env.index += 1; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import arrowFunction from './arrow-function/jsep-arrow-function.js'; | ||
import assignment from './assignment/jsep-assignment.js'; | ||
import ignoreComments from './ignore-comments/jsep-ignore-comments.js'; | ||
import newExpression from './new/jsep-new.js'; | ||
import object from './object/jsep-object.js'; | ||
import templateLiteral from './template-literal/jsep-template-literal.js'; | ||
|
||
export { | ||
arrowFunction, | ||
assignment, | ||
ignoreComments, | ||
newExpression, | ||
object, | ||
templateLiteral, | ||
}; | ||
|
||
export default [ | ||
arrowFunction, | ||
assignment, | ||
ignoreComments, | ||
newExpression, | ||
object, | ||
templateLiteral, | ||
]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
export default function (jsep) { | ||
if (typeof jsep === 'undefined') { | ||
return; | ||
} | ||
|
||
jsep.addUnaryOp('new'); | ||
|
||
jsep.hooks.add('after-token', function gobbleNew(env) { | ||
const node = env.node; | ||
if (node && node.operator === 'new') { | ||
if (!node.argument || node.argument.type !== 'CallExpression') { | ||
env.throwError('Expected new function()'); | ||
} | ||
env.node = node.argument; | ||
env.node.type = 'NewExpression'; | ||
} | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
export default function (jsep) { | ||
if (typeof jsep === 'undefined') { | ||
return; | ||
} | ||
|
||
const PERIOD_CODE = 46; // '.' | ||
const OCURLY_CODE = 123; // { | ||
const CCURLY_CODE = 125; // } | ||
const OBJECT_EXPRESSION = 'ObjectExpression'; | ||
const PROPERTY = 'Property'; | ||
const SPREAD_ELEMENT = 'SpreadElement'; | ||
jsep.addBinaryOp(':', 0.5); | ||
|
||
const gobbleObject = function (type) { | ||
return function (env) { | ||
if (env.exprICode(env.index) === OCURLY_CODE) { | ||
env.index++; | ||
const args = env.gobbleArguments(CCURLY_CODE); | ||
const properties = args.map((arg) => { | ||
if (arg.type === 'SpreadElement') { | ||
return arg; | ||
} | ||
if (arg.type === 'Identifier') { | ||
return { | ||
type: PROPERTY, | ||
computed: false, | ||
key: arg.name, | ||
shorthand: true, | ||
}; | ||
} | ||
if (arg.type === 'BinaryExpression') { | ||
const computed = arg.left.type === 'ArrayExpression'; | ||
return { | ||
type: PROPERTY, | ||
computed, | ||
key: computed | ||
? arg.left.elements[0] | ||
: arg.left, | ||
value: arg.right, | ||
shorthand: false, | ||
}; | ||
} | ||
env.throwError('Unexpected object property'); | ||
}); | ||
|
||
env.node = { | ||
type, | ||
properties, | ||
}; | ||
} | ||
}; | ||
}; | ||
jsep.hooks.add('gobble-expression', gobbleObject(OBJECT_EXPRESSION)); | ||
jsep.hooks.add('after-token', gobbleObject(OBJECT_EXPRESSION)); | ||
|
||
jsep.hooks.add('gobble-token', function gobbleSpread(env) { | ||
// check for spread operator: | ||
if ([0, 1, 2].every(i => env.exprICode(env.index + i) === PERIOD_CODE)) { | ||
env.index += 3; | ||
env.node = { | ||
type: SPREAD_ELEMENT, | ||
argument: env.gobbleExpression(), | ||
}; | ||
} | ||
}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we switch to ESM-style imports here?